home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Celestin Apprentice 5
/
Apprentice-Release5.iso
/
Environments
/
PowerMacOberon feb96
/
Source
/
POPC.Mod
(
.txt
)
< prev
next >
Encoding:
Amiga
Atari
Commodore
DOS
FM Towns/JPY
Macintosh
Macintosh JP
Macintosh to JP
NeXTSTEP
RISC OS/Acorn
Shift JIS
UTF-8
Wrap
Oberon Text
|
1996-01-25
|
86.7 KB
|
2,227 lines
|
[
TEXT/.Ob4
]
Syntax10b.Scn.Fnt
Syntax10.Scn.Fnt
Syntax10i.Scn.Fnt
InfoElems
Alloc
Syntax10.Scn.Fnt
StampElems
Alloc
25 Jan 96
"Title":
"Author":
"Abstract":
"Keywords":
"Version":
"From": 04.07.95 13:54:44
"Until":
"Changes":
mah/mk 4.7.95 NIL checks on less equal zero removed because of supposed
negative pointer values from Printer.SetPort
mah 14.8.95 Store Condition modified to correct buf with BOOL expressions
cf:=FALSE; c:=TRUE; cf:=c OR cf; -> endless loop
Syntax12b.Scn.Fnt
Syntax12.Scn.Fnt
FoldElems
Syntax10.Scn.Fnt
Syntax10b.Scn.Fnt
PROCEDURE MskAsh* (VAR x, y, z: OPL.Item; rt: LONGINT);
BEGIN
ASSERT(y.mode = Con);
Msk(x, y, -1); Ash(x, z, rt)
END MskAsh;
PROCEDURE AshMsk* (VAR x, y, z: OPL.Item; rt: LONGINT);
VAR sh, mb: LONGINT;
BEGIN
ASSERT(z.mode = Con);
IF y.mode = Con THEN mb := CNTLZ(-1-z.offset); sh := y.offset;
IF sh > 0 THEN
IF mb+sh < 24 THEN MakeReg(x, -1) END;
OPL.FreeTempR(x.reg); rt := CheckR(rt); OPL.Put(iRLINM+rt*fRA+x.reg*fRS+sh*fSH+mb*fMB+(31-sh)*fME); x.reg := rt
ELSIF SYSTEM.VAL(SET, ASH(80000000H, sh)) * SYSTEM.VAL(SET, -1-z.offset) = {} THEN
IF mb < 24 THEN MakeReg(x, -1) END;
OPL.FreeTempR(x.reg); rt := CheckR(rt); OPL.Put(iRLINM+rt*fRA+x.reg*fRS+(sh MOD 32)*fSH+mb*fMB+31*fME); x.reg := rt
ELSE
Ash(x, y, -1); Msk(x, z, rt)
END
ELSE
Ash(x, y, -1); Msk(x, z, rt)
END
END AshMsk;
Syntax10.Scn.Fnt
t1 := OPL.GetTempR(); OPL.Put(iCAL+t1*fRT+4); OPL.Put(iMTSPR+t1*fRS+spXER*fSPR);
LoadAddr(x, -1); LoadAddr(y, -1); OPL.Put(iCAL);
s1 := x.reg; s2 := y.reg; t2 := OPL.GetTempR(); f := OPL.GetTempCRF();
b := OPL.GetCRF0(); IF b # 0 THEN OPM.err(215) END;
lstlab := 0; SetLabel(lstlab); OPL.Put(iLSCBX+t1*fRT+s1*fRA+fREC); OPL.Put(iLSCBX+t2*fRT+s2*fRA);
lastlab := 0; PutBranchInstr(iBM, lastlab); OPL.Put(iCMPL+f*fBF+t1*fRA+t2*fRB);
OPL.Put(iAI+4); endlab := 0; PutBranchInstr(iBF+(f*4+bEQ)*fBI, endlab); PutBranch(lstlab);
SetLabel(lastlab); OPL.Put(iMFSPR+spXER*fSPR); OPL.Put(iSFI+4);
OPL.Put(iRLINM+3*fSH+28*fME); OPL.Put(iSR+t1*fRS+t1*fRA); OPL.Put(iSR+t2*fRS+t2*fRA);
OPL.Put(iCMPL+f*fBF+t1*fRA+t2*fRB); SetLabel(endlab);
OPL.FreeTempCRBs({b*4..b*4+3}); OPL.FreeTempR(s1); OPL.FreeTempR(s2);
OPL.FreeTempR(t1); OPL.FreeTempR(t2)
MODULE POPC; (* mmb 4.3.91 / 20.11.94 *)
IMPORT
OPL := POPL, OPT := POPT, OPM := POPM, SYSTEM;
CONST
(* symbol values and ops *)
times = 1; slash = 2; div = 3; mod = 4; and = 5; plus = 6; minus = 7; or = 8; eql = 9;
neq = 10; lss = 11; leq = 12; gtr = 13; geq = 14; in = 15; is = 16; ash = 17; msk = 18; len = 19;
conv = 20; abs = 21; cap = 22; odd = 23; not = 32;
(*SYSTEM*)
adr = 24; cc = 25; bit = 26; lsh = 27; rot = 28; val = 29;
(* structure forms *)
Undef = 0; Byte = 1; Bool = 2; Char = 3; SInt = 4; Int = 5; LInt = 6;
Real = 7; LReal = 8; Set = 9; String = 10; NilTyp = 11; NoTyp = 12;
Pointer = 13; ProcTyp = 14; Comp = 15;
(* structure sets *)
RealTypes = {Real, LReal};
(* composite structure forms *)
Basic = 1; Array = 2; DynArr = 3; Record = 4;
(* nodes classes *)
Nvar = 0; Nvarpar = 1; Nfield = 2; Nderef = 3; Nindex = 4; Nguard = 5; Neguard = 6;
Nconst = 7; Ntype = 8; Nproc = 9; Nupto = 10; Nmop = 11; Ndop = 12; Ncall = 13;
Ninittd = 14; Nif = 15; Ncaselse = 16; Ncasedo = 17; Nenter = 18; Nassign = 19;
Nifelse =20; Ncase = 21; Nwhile = 22; Nrepeat = 23; Nloop = 24; Nexit = 25;
Nreturn = 26; Nwith = 27; Ntrap = 28;
(* item/object modes *)
Var = 1; VarPar = 2; Con = 3; Fld = 4; Typ = 5; LProc = 6; XProc = 7; SProc = 8; CProc = 9; IProc = 10;
Head = 12; Based = 14; Indexed = 15; Reg = 16; RegSI = 17; FReg = 18; Cond = 19;
(* compiler options: *)
inxchk = 0; (* index check on *)
ovflchk = 1; (* overflow check on *)
ranchk = 2; (* range check on *)
typchk = 3; (* type check on *)
newsf = 4; (* generation of new symbol file allowed *)
ptrinit = 5; (* pointer initialization *)
nilchk = 7; (* nil checks *)
powerpc = 10; (* use PowerPC instruction set *)
(* fields in the POWER architecture instruction encoding *)
fAA = 00000002H;
fBA = 00010000H;
fBB = 00000800H;
fBD = 00000004H;
fBF = 00800000H;
fBFA = 00040000H;
fBI = 00010000H;
fBO = 00200000H;
fBT = 00200000H;
fD = 00000001H;
fEO = 00000002H;
fEO1 = 00000002H;
fFXM = 00001000H;
fFLM = 00020000H;
fFRA = 00010000H;
fFRB = 00000800H;
fFRC = 00000040H;
fFRS = 00200000H;
fFRT = 00200000H;
fI = 00001000H;
fLI = 00000004H;
fMB = 00000040H;
fME = 00000002H;
fNB = 00000800H;
fOE = 00000400H;
fOPCD = 04000000H;
fRA = 00010000H;
fRB = 00000800H;
fRS = 00200000H;
fRT = 00200000H;
fSH = 00000800H;
fSI = 00000001H;
fSPR = 00010000H;
fTO = 00200000H;
fLK = 00000001H;
fUI = 00000001H;
fXO = 00000002H;
fREC = 1;
(* condition code bits *)
bLT = 0; bGT = 1; bEQ = 2; bSO = 3;
(* special register definitions *)
SB = 2; SP = 1; SLpar = 11; virtualFP = 32; spCTR = 9; spMQ = 0; spLR = 8; spXER = 1;
(* opcodes of the POWER architecture *)
iA = 7C000014H;
iADDC = iA;
iABS = 7C0002D0H;
iAE = 7C000114H;
iAI = 30000000H;
iADDIC = iAI;
iADDICR = 34000000H;
iAME = 7C0001D4H;
iAND = 7C000038H;
iANDC = 7C000078H;
iANDIL = 70000000H;
iANDIU = 74000000H;
iAZE = 7C000194H;
iB = 48000000H;
iBC = 40000000H;
iBCC = 4C000420H;
iBCR = 4C000020H;
iCAL = 38000000H;
iCAU = 3C000000H;
iCAX = 7C000214H;
iADDI = iCAL;
iADD = iCAX;
iCLCS = 7C000426H;
iCLF = 7C0000ECH;
iCLI = 7C0003ECH;
iCMP = 7C000000H;
iCMPI = 2C000000H;
iCMPL = 7C000040H;
iCMPLI = 28000000H;
iCNTLZ = 7C000034H;
iCRAND = 4C000202H;
iCRANDC = 4C000102H;
iCREQV = 4C000242H;
iCRNAND = 4C0001C2H;
iCRNOR = 4C000042H;
iCROR = 4C000382H;
iCRORC = 4C000342H;
iCRXOR = 4C000182H;
iDCLST = 7C0004ECH;
iDCLZ = 7C0007ECH;
iDCS = 7C0004ACH;
iDIV = 7C000296H;
iDIVS = 7C0002D6H;
iDOZ = 7C000210H;
iDOZI = 24000000H;
iEQV = 7C000238H;
iEXTS = 7C000734H;
iEXTSB = 7C000774H;
iFA = 0FC00002AH;
iFADDS = 0EC00002AH;
iFABS = 0FC000210H;
iFCMPO = 0FC000040H;
iFCMPU = 0FC000000H;
iFD = 0FC000024H;
iFDIVS = 0EC000024H;
iFM = 0FC000032H;
iFMULS = 0EC000032H;
iFMA = 0FC00003AH;
iFMADDS = 0EC00003AH;
iFMR = 0FC000090H;
iFMS = 0FC000038H;
iFMSUBS = 0EC000038H;
iFNABS = 0FC000110H;
iFNEG = 0FC000050H;
iFNMA = 0FC00003EH;
iFNMADDS = 0EC00003EH;
iFNMS = 0FC00003CH;
iFNMSUBS = 0EC00003CH;
iFRSP = 0FC000018H;
iFS = 0FC000028H;
iFSUBS = 0EC000028H;
iICS = 4C00012CH;
iL = 080000000H;
iLBRX = 7C00042CH;
iLBZ = 088000000H;
iLBZU = 08C000000H;
iLBZUX = 7C0000EEH;
iLBZX = 7C0000AEH;
iLFD = 0C8000000H;
iLFDU = 0CC000000H;
iLFDUX = 7C0004EEH;
iLFDX = 7C0004AEH;
iLFS = 0C0000000H;
iLFSU = 0C4000000H;
iLFSUX = 7C00046EH;
iLFSX = 7C00042EH;
iLHA = 0A8000000H;
iLHAU = 0AC000000H;
iLHAUX = 7C0002EEH;
iLHAX = 7C0002AEH;
iLHBRX = 7C00062CH;
iLHZ = 0A0000000H;
iLHZU = 0A4000000H;
iLHZUX = 7C00026EH;
iLHZX = 7C00022EH;
iLM = 0B8000000H;
iLSCBX = 7C00022AH;
iLSI = 7C0004AAH;
iLSX = 7C00042AH;
iLU = 084000000H;
iLUX = 7C00006EH;
iLX = 7C00002EH;
iMASKG = 7C00003AH;
iMASKIR = 7C00043AH;
iMCRF = 4C000000H;
iMCRFS = 0FC000080H;
iMCRXR = 7C000400H;
iMFCR = 7C000026H;
iMFFS = 0FC00048EH;
iMFMSR = 7C0000A6H;
iMFSPR = 7C0002A6H;
iMFSR = 7C0004A6H;
iMFSRI = 7C0004E6H;
iMTCRF = 7C000120H;
iMTFSB0 = 0FC00008CH;
iMTFSB1 = 0FC00004CH;
iMTFSF = 0FC00058EH;
iMTSFI = 0FC00010CH;
iMTMSR = 7C000124H;
iMTSPR = 7C0003A6H;
iMTXER = iMTSPR+spXER*fSPR;
iMTSR = 7C0001A4H;
iMTSRI = 7C0001E4H;
iMUL = 7C0000D6H;
iMULI = 1C000000H;
iMULS = 7C0001D6H;
iNABS = 7C0003D0H;
iNAND = 7C0003B8H;
iNEG = 7C0000D0H;
iNOR = 7C0000F8H;
iOR = 7C000378H;
iORC = 7C000338H;
iORIL = 60000000H;
iORIU = 64000000H;
iRAC = 7C000664H;
iRFI = 4C000064H;
iRFSVC = 4C0000A4H;
iRLIMI = 50000000H;
iRLINM = 54000000H;
iRLMI = 58000000H;
iRLNM = 5C000000H;
iRRIB = 7C000432H;
iSF = 7C000010H;
iSFE = 7C000110H;
iSFI = 20000000H;
iSFME = 7C0001D0H;
iSFZE = 7C000190H;
iSL = 7C000030H;
iSLE = 7C000132H;
iSLEQ = 7C0001B2H;
iSLIQ = 7C000170H;
iSLLIQ = 7C0001F0H;
iSLLQ = 7C0001B0H;
iSLQ = 7C000130H;
iSR = 7C000430H;
iSRA = 7C000630H;
iSRAI = 7C000670H;
iSRAIQ = 7C000770H;
iSRAQ = 7C000730H;
iSRE = 7C000532H;
iSREA = 7C000732H;
iSREQ = 7C0005B2H;
iSRIQ = 7C000570H;
iSRLIQ = 7C0005F0H;
iSRLQ = 7C0005B0H;
iSRQ = 7C000530H;
iST = 90000000H;
iSTB = 98000000H;
iSTBRX = 7C00052CH;
iSTBU = 9C000000H;
iSTBUX = 7C0001EEH;
iSTBX = 7C0001AEH;
iSTFD = 0D8000000H;
iSTFDU = 0DC000000H;
iSTFDUX = 7C0005EEH;
iSTFDX = 7C0005AEH;
iSTFS = 0D0000000H;
iSTFSU = 0D4000000H;
iSTFSUX = 7C00056EH;
iSTFSX = 7C00052EH;
iSTH = 0B0000000H;
iSTHBRX = 7C00072CH;
iSTHU = 0B4000000H;
iSTHUX = 7C00036EH;
iSTHX = 7C00032EH;
iSTM = 0BC000000H;
iSTSI = 7C0005AAH;
iSTSX = 7C00052AH;
iSTU = 94000000H;
iSTUX = 7C00016EH;
iSTX = 7C00012EH;
iSVC = 44000000H;
iT = 7C000008H;
iTI = 0C000000H;
iTLBI = 7C000264H;
iXOR = 7C000278H;
iXORIL = 68000000H;
iXORIU = 6C000000H;
iBCNT = iBC+16*fBO;
iBDNZ = iBCNT;
iBDZ = iBC+18*fBO;
iNOT = iSFI+0FFFFH;
iUPPER = 4000000H;
iBT = iBC+15*fBO;
iBF = iBC+7*fBO;
iBA = iBC+31*fBO;
iBCNTNZ = iBC+16*fBO;
iBCNTNZNM = iBC+0*fBO+bEQ*fBI;
iBM = iBT+bEQ*fBI;
iBNM = iBF+bEQ*fBI;
iLIL = iCAL;
cALWAYS = 1FH;
(* trap numbers *)
IndexCheck = 1; DivideTrap = 2; CaseTrap = 3; TypeGuard = 4; FuncTrap = 5; DimTrap = 6; NilTrap = 7;
(* trap fields *)
tUGE = 5; tULE = 6; tNEQ = 27; tEQ = 4; tSLE = 20; tALWAYS = 31;
(* tags *)
SYSMTag = 0FFX; NewRecETag = 0FFX; NewSysETag = 0FEX; NewArrETag = 0FDX;
LinkMTag = 0FEX; CaseETag = 0FFX;
LowWord = 10000H;
FP: LONGINT;
BLI, XLI, BSI, XSI: ARRAY Pointer+1 OF LONGINT;
options: SET;
IntToRealAddr, RealToIntAddr, scratch: LONGINT;
IntToRealBlock, RealToIntBlock: ARRAY 16 OF CHAR;
zero, CAPmask: OPL.Item;
LoopLevel: INTEGER;
leaveProc: OPL.Label;
FPlink, FPlink4: OPL.Label;
LoopStart, LoopEnd: ARRAY OPM.MaxExit OF OPL.Label;
CRbit, switch: ARRAY geq-eql+1 OF INTEGER;
aopSize, sSize, SLsize: LONGINT;
SBoffset, CaseLink: LONGINT;
NewRecEntry, NewSysEntry, NewArrEntry: LONGINT;
PROCEDURE CNTLZ (i: LONGINT): LONGINT;
VAR j: LONGINT; s: SET;
BEGIN
IF OPM.CeresVersion THEN s := SYSTEM.VAL(SET, i); j := 31; (* note: Ceres specific *)
WHILE ~(j IN s) & (j >= 0) DO DEC(j) END;
RETURN 31-j
ELSE
s := SYSTEM.VAL(SET, i); j := 0;
WHILE ~(j IN s) & (j < 32) DO INC(j) END;
RETURN j
END
END CNTLZ;
PROCEDURE MoveReg(rt, rs: LONGINT);
BEGIN
IF rs # 0 THEN OPL.Put(iCAL+rt*fRT+rs*fRA) ELSE OPL.Put(iAI+rt*fRT+rs*fRA) END
END MoveReg;
PROCEDURE IMIN (a, b: LONGINT): LONGINT;
BEGIN IF a < b THEN RETURN a ELSE RETURN b END
END IMIN;
PROCEDURE CheckR (rt: LONGINT): LONGINT;
BEGIN IF rt < 0 THEN RETURN OPL.GetTempR() ELSE RETURN rt END
END CheckR;
PROCEDURE CheckF (rt: LONGINT): LONGINT;
BEGIN IF rt < 0 THEN RETURN OPL.GetTempF() ELSE RETURN rt END
END CheckF;
PROCEDURE CheckCRB (rt: LONGINT): LONGINT;
BEGIN IF rt < 0 THEN RETURN OPL.GetTempCRB() ELSE RETURN rt END
END CheckCRB;
PROCEDURE CheckVFP (r: LONGINT): LONGINT;
BEGIN (*IF r = virtualFP THEN OPL.FixMark; RETURN SP ELSE RETURN r END*) RETURN r
END CheckVFP;
PROCEDURE^ Load* (VAR x: OPL.Item; rt: LONGINT);
PROCEDURE^ RegToCond (VAR x: OPL.Item);
PROCEDURE PutBranchInstr (instr: LONGINT; VAR l: OPL.Label);
VAR ll: LONGINT;
BEGIN
IF l > 0 THEN ll := l-OPL.pc ELSE ll := l END;
ll := ll MOD 4000H; OPL.Put(instr+ll*4);
IF l <= 0 THEN l := SHORT(-OPL.pc+1) END
END PutBranchInstr;
PROCEDURE PutBranch* (VAR l: OPL.Label);
BEGIN PutBranchInstr(iBA, l)
END PutBranch;
PROCEDURE PutCondBranch* (VAR x: OPL.Item; Tjmp: BOOLEAN);
VAR pospol: BOOLEAN; cbit, l: LONGINT;
BEGIN
IF x.mode = Con THEN
IF Tjmp = (x.offset # 1) THEN RETURN (* optimize untaken or taken branches *)
ELSIF Tjmp THEN PutBranch(x.Tjmp)
ELSE PutBranch(x.Fjmp)
END
END;
IF x.mode # Cond THEN Load(x, -1); RegToCond(x) END;
cbit := x.reg; pospol := cbit >= 0; IF ~pospol THEN cbit := -1-cbit END;
IF Tjmp THEN l := x.Tjmp ELSE l := x.Fjmp END;
IF l > 0 THEN l := l-OPL.pc END; l := l MOD 4000H; OPL.FreeTempCRBs({cbit});
IF pospol = Tjmp THEN OPL.Put(iBT+cbit*fBI+l*4) ELSE OPL.Put(iBF+cbit*fBI+l*4) END;
IF Tjmp THEN
IF x.Tjmp <= 0 THEN x.Tjmp := SHORT(-OPL.pc+1) END
ELSE
IF x.Fjmp <= 0 THEN x.Fjmp := SHORT(-OPL.pc+1) END
END
END PutCondBranch;
PROCEDURE SetLabel* (VAR l: OPL.Label);
BEGIN
IF l < 0 THEN OPL.Fixup(l) ELSE l := SHORT(OPL.pc) END
END SetLabel;
PROCEDURE MoveCond (VAR x: OPL.Item; rt: LONGINT): LONGINT;
VAR instr, src: LONGINT; l: OPL.Label;
BEGIN
src := x.reg; l := 0;
IF (x.Tjmp = 0) & (x.Fjmp = 0) THEN
IF src < 0 THEN src := -1-src; instr := iCRNOR ELSE instr := iCROR END;
OPL.FreeTempCRBs({src}); rt := CheckCRB(rt); OPL.Put(instr+rt*fBT+src*fBA+src*fBB)
ELSE
rt := CheckCRB(rt); PutCondBranch(x, FALSE);
OPL.Fixup(x.Tjmp); OPL.Put(iCREQV+rt*fBT); PutBranch(l);
OPL.Fixup(x.Fjmp); OPL.Put(iCRXOR+rt*fBT); OPL.Fixup(l)
END;
RETURN rt
END MoveCond;
PROCEDURE CondToReg (VAR x: OPL.Item; rt: LONGINT);
VAR src, t: LONGINT; l: OPL.Label;
BEGIN
ASSERT(x.mode = Cond);
src := x.reg;
IF (x.Tjmp = 0) & (x.Fjmp = 0) THEN
src := x.reg; IF src < 0 THEN src := MoveCond(x, -1) END;
OPL.FreeTempCRBs({src}); t := OPL.GetTempR(); OPL.Put(iMFCR+t*fRT);
OPL.FreeTempR(t); rt := CheckR(rt); OPL.Put(iRLINM+rt*fRA+t*fRS+((src+1) MOD 32)*fSH+31*fMB+31*fME);
ELSE
rt := CheckR(rt); PutCondBranch(x, FALSE);
SetLabel(x.Tjmp); OPL.Put(iCAL+rt*fRT+1); l := 0; PutBranch(l);
SetLabel(x.Fjmp); OPL.Put(iCAL+rt*fRT); SetLabel(l)
END;
x.mode := Reg; x.reg := rt
END CondToReg;
PROCEDURE RegToCond (VAR x: OPL.Item);
VAR src, t: LONGINT;
BEGIN
ASSERT(x.mode IN {Reg, RegSI});
src := x.reg; OPL.FreeTempR(src); t := OPL.GetTempCRF(); OPL.Put(iCMPI+t*fBF+src*fRA+0); (* << mmb 16.12.91 *)
t := t*4; OPL.FreeTempCRBs({t..t+3}-{t+bEQ}); x.mode := Cond; x.reg := -1-(t+bEQ)
END RegToCond;
PROCEDURE FindFP (curlev, tofind, rt: LONGINT): LONGINT;
VAR y: OPL.Item;
BEGIN
ASSERT(curlev >= tofind);
IF curlev = tofind THEN RETURN FP
ELSE
y.mode := Based; y.reg := FP; y.offset := -4; y.typ := OPT.linttyp; y.dreg := -1;
WHILE curlev > tofind+1 DO Load(y, -1); y.mode := Based; y.offset := -4; DEC(curlev) END;
Load(y, rt); RETURN y.reg
END
END FindFP;
PROCEDURE ReduceIndex (VAR x: OPL.Item; inx, rt: LONGINT);
VAR src: LONGINT;
BEGIN
ASSERT(x.mode IN {Indexed, Based});
src := x.reg; OPL.FreeTempR(src); OPL.FreeTempR(inx); rt := CheckR(rt);
OPL.Put(iCAX+rt*fRT+src*fRA+inx*fRB); x.reg := rt
END ReduceIndex;
PROCEDURE BaseOrInx (VAR x: OPL.Item; rt: LONGINT);
VAR offset, mnolev, t: LONGINT; typ: OPT.Struct; DArr: BOOLEAN;
BEGIN
DArr := x.typ.comp = DynArr;
CASE x.mode OF
Based, Indexed:
| Var, VarPar:
mnolev := x.mnolev;
IF mnolev < 0 THEN
offset := x.offset; typ := x.typ; x.mode := Based; x.reg := SB;
x.offset := -(mnolev*4)+OPL.linkTable; x.typ := OPT.linttyp;
t := rt; IF offset # 0 THEN t := -1 END;
Load(x, t); x.mode := Based; x.offset := offset; x.typ := typ
ELSIF mnolev = 0 THEN
x.mode := Based; x.reg := SB
ELSIF (x.mode = VarPar) OR DArr THEN
x.reg := FindFP(OPL.level, x.mnolev, -1);
IF DArr THEN t := x.reg; offset := x.offset END;
x.mode := Based; typ := x.typ; x.typ := OPT.linttyp; Load(x, -1);
x.mode := Based; x.offset := 0; x.typ := typ;
IF DArr THEN x.dreg := SHORT(SHORT(t)); x.adr := offset; x.dmode := Based END
ELSE
x.reg := FindFP(OPL.level, x.mnolev, -1); x.mode := Based
END
ELSE OPM.err(127) (* illegal use of object *)
END
END BaseOrInx;
PROCEDURE Base (VAR x: OPL.Item; rt: LONGINT);
BEGIN
IF x.mode = Indexed THEN ReduceIndex(x, x.offset, rt); x.mode := Based; x.offset := 0 ELSE BaseOrInx(x, rt) END;
ASSERT(x.mode = Based);
END Base;
PROCEDURE ShortBase (VAR x: OPL.Item; rt: LONGINT);
VAR u, l, base: LONGINT;
BEGIN
ASSERT(x.mode = Based);
u := x.offset; l := u MOD LowWord; u := (SYSTEM.LSH(u, -16)+SYSTEM.LSH(l, -15)) MOD LowWord;
IF u # 0 THEN
base := x.reg; OPL.FreeTempR(base); rt := CheckR(rt); OPL.Put(iCAU+rt*fRT+base*fRA+u); x.reg := rt;
x.offset := ASH(SYSTEM.LSH(l, 16), -16)
END;
END ShortBase;
PROCEDURE MakeReg (VAR x: OPL.Item; rt: LONGINT);
VAR s, t: LONGINT;
BEGIN
ASSERT(x.mode IN {Reg, RegSI});
IF x.mode = RegSI THEN
s := x.reg; OPL.FreeTempR(s);
IF powerpc IN options THEN
rt := CheckR(rt); OPL.Put(iEXTSB+rt*fRA+s*fRS)
ELSE
t := OPL.GetTempR(); OPL.Put(iRLINM+t*fRA+s*fRS+24*fSH+31*fME);
OPL.FreeTempR(t); rt := CheckR(rt); OPL.Put(iSRAI+rt*fRA+t*fRS+24*fSH)
END;
x.reg := rt; x.mode := Reg
END
END MakeReg;
PROCEDURE LoadAddr* (VAR x: OPL.Item; rt: LONGINT);
VAR u, l, base, inx, t: LONGINT;
BEGIN
BaseOrInx(x, rt); base := x.reg;
IF x.mode = Based THEN
u := x.offset; l := u MOD LowWord; u := (SYSTEM.LSH(u, -16)+SYSTEM.LSH(l, -15)) MOD LowWord;
IF u # 0 THEN
ASSERT(base # virtualFP);
OPL.FreeTempR(base);
IF l # 0 THEN
t := OPL.GetTempR(); OPL.Put(iCAU+t*fRT+base*fRA+u);
OPL.FreeTempR(t); rt := CheckR(rt); OPL.Put(iCAL+rt*fRT+t*fRA+l)
ELSE
rt := CheckR(rt); OPL.Put(iCAU+rt*fRT+base*fRA+u)
END
ELSIF l # 0 THEN
base := CheckVFP(base); OPL.FreeTempR(base); rt := CheckR(rt); OPL.Put(iCAL+rt*fRT+base*fRA+l)
ELSIF base = 0 THEN (* load constant 0 *)
rt := CheckR(rt); OPL.Put(iCAL+rt*fRT)
ELSE rt := base (* do not move *)
END
ELSE
ASSERT(base # virtualFP); inx := x.offset;
OPL.FreeTempR(base); OPL.FreeTempR(inx); rt := CheckR(rt); OPL.Put(iCAX+rt*fRT+base*fRA+inx*fRB)
END;
IF x.dreg # -1 THEN OPL.UnholdTempR(x.dreg);
IF x.dreg # rt THEN OPL.FreeTempR(x.dreg) END;
x.dreg := -1
END;
x.mode := Reg; x.reg := rt; x.typ := OPT.linttyp
END LoadAddr;
PROCEDURE Load* (VAR x: OPL.Item; rt: LONGINT);
VAR form, base: LONGINT; RealType: BOOLEAN;
BEGIN
form := x.typ^.form; RealType := form IN RealTypes;
ASSERT(x.typ^.form IN {Byte, Bool, Char, SInt, Int, LInt, Real, LReal, Set, NilTyp, Pointer});
CASE x.mode OF
Reg, RegSI, FReg, Cond:
rt := x.reg
| Var, VarPar, Based:
BaseOrInx(x, -1); ShortBase(x, -1);
ASSERT(x.mode = Based);
base := x.reg; OPL.FreeTempR(base); base := CheckVFP(base);
IF RealType THEN rt := CheckF(rt); x.mode := FReg ELSE rt := CheckR(rt); x.mode := Reg END;
OPL.Put(BLI[form]+rt*fRT+base*fRA+(x.offset MOD LowWord));
IF form = SInt THEN x.mode := RegSI END
| Indexed:
base := x.reg; OPL.FreeTempR(base); ASSERT(base # virtualFP);
IF RealType THEN rt := CheckF(rt); x.mode := FReg ELSE rt := CheckR(rt); x.mode := Reg END;
OPL.Put(XLI[form]+rt*fRT+base*fRA+x.offset*fRB); OPL.FreeTempR(x.offset);
IF form = SInt THEN x.mode := RegSI END
| Con:
ASSERT(x.typ^.form IN {Byte, Bool, Char, SInt, Int, LInt, Set, NilTyp, Pointer});
x.mode := Based; x.reg := 0; LoadAddr(x, rt); rt := x.reg
END;
x.reg := rt;
IF x.dreg # -1 THEN OPL.UnholdTempR(x.dreg);
IF (x.dreg # rt) OR RealType THEN OPL.FreeTempR(x.dreg) END;
x.dreg := -1
END
END Load;
PROCEDURE Store (VAR x, y: OPL.Item);
VAR smode, dmode, dest, src, inx, form: LONGINT;
BEGIN
ASSERT((x.typ^.form = y.typ^.form) &
(x.typ^.form IN {Byte, Bool, Char, SInt, Int, LInt, Real, LReal, Set, Pointer, NilTyp}));
form := x.typ^.form; smode := y.mode; dmode := x.mode;
ASSERT(y.mode IN {Reg, RegSI, FReg, Cond});
IF (form = Bool) & ((y.Tjmp # 0) OR (y.Fjmp # 0)) & (smode # Cond) THEN RegToCond(y); smode := Cond END;
CASE dmode OF
Reg, RegSI:
dest := x.reg;
IF smode = Cond THEN CondToReg(y, dest) END;
IF y.mode = RegSI THEN MakeReg(y, dest) END;
IF y.reg # dest THEN src := y.reg; OPL.FreeTempR(src); MoveReg(dest, src) END
| FReg:
src := y.reg; dest := x.reg; IF src # dest THEN OPL.FreeTempF(src); OPL.Put(iFMR+x.reg*fFRT+src*fFRB) END
| Cond:
dest := x.reg;
IF smode = Reg THEN RegToCond(y) END;
IF (y.Tjmp # 0) OR (y.Fjmp # 0) OR (y.reg # dest) THEN y.reg := MoveCond(y, dest); ASSERT(y.reg = dest) END (* mah *)
(* IF y.reg # dest THEN y.reg := MoveCond(y, dest); ASSERT(y.reg = dest) END *)
| Var, VarPar, Based:
BaseOrInx(x, -1);
IF smode = Cond THEN CondToReg(y, -1)
ELSIF smode = RegSI THEN MakeReg(y, -1)
END;
ShortBase(x, -1); src := y.reg; dest := x.reg;
IF smode = FReg THEN OPL.FreeTempF(src) ELSE OPL.FreeTempR(src) END;
OPL.FreeTempR(dest); OPL.Put(BSI[form]+src*fRS+dest*fRA+(x.offset MOD LowWord))
| Indexed:
IF smode = Cond THEN CondToReg(y, -1)
ELSIF smode = RegSI THEN MakeReg(y, -1)
END;
src := y.reg; dest := x.reg; inx := x.offset;
IF smode = FReg THEN OPL.FreeTempF(src) ELSE OPL.FreeTempR(src) END;
OPL.FreeTempR(dest); OPL.FreeTempR(inx); OPL.Put(XSI[form]+src*fRS+dest*fRA+inx*fRB)
END;
IF x.dreg # -1 THEN OPL.UnholdTempR(x.dreg); OPL.FreeTempR(x.dreg); x.dreg := -1 END
END Store;
PROCEDURE Move (VAR x, y, z: OPL.Item; aligned8: BOOLEAN);
VAR src, dest, r1, r2, iter, slack, h, l: LONGINT; loop, loopend: OPL.Label;
BEGIN
(* this is the long version *)
loop := 0; loopend := 0;
IF z.mode = Con THEN
iter := z.offset DIV 8; slack := z.offset MOD 8;
r1 := OPL.GetTempRegs(2, {}); r2 := r1+1;
IF iter > 0 THEN
Base(x, -1); Base(y, -1);
(* before entering the pipelined loop, dest is at offset -4, src at offset 0 *)
DEC(x.offset, 4); LoadAddr(x, -1); LoadAddr(y, -1); src := y.reg; dest := x.reg;
IF ~(src IN OPL.TempRegs) THEN src := OPL.GetTempR(); MoveReg(src, y.reg) END;
IF ~(dest IN OPL.TempRegs) THEN dest := OPL.GetTempR(); MoveReg(dest, x.reg) END;
IF iter > 1 THEN DEC(iter);
IF iter > 1 THEN
IF iter > 32767 THEN
l := iter MOD LowWord; h := (SYSTEM.LSH(iter, -16)+SYSTEM.LSH(l, -15)) MOD LowWord;
OPL.Put(iCAU+r1*fRT+h); OPL.Put(iCAL+r1*fRT+r1*fRA+l)
ELSE
OPL.Put(iCAL+r1*fRT+iter)
END;
OPL.Put(iMTSPR+r1*fRS+spCTR*fSPR)
END;
OPL.Put(iL+r1*fRT+src*fRA+0); OPL.Put(iL+r2*fRT+src*fRA+4);
SetLabel(loop);
OPL.Put(iST+r1*fRS+dest*fRA+4); OPL.Put(iLU+r1*fRT+src*fRA+8);
OPL.Put(iSTU+r2*fRS+dest*fRA+8); OPL.Put(iL+r2*fRT+src*fRA+4);
IF iter > 1 THEN PutBranchInstr(iBCNTNZ, loop) END;
OPL.Put(iST+r1*fRS+dest*fRA+4); OPL.Put(iST+r2*fRS+dest*fRA+8)
(* now, dest is at offset -12, and src at offset -8 *)
ELSE
OPL.Put(iL+r1*fRT+src*fRA+0); OPL.Put(iL+r2*fRT+src*fRA+4);
OPL.Put(iST+r1*fRS+dest*fRA+4); OPL.Put(iST+r2*fRS+dest*fRA+8)
(* as above, dest is at offset -12, src at offset -8 *)
END;
IF slack > 0 THEN OPL.Put(iCAL+src*fRT+src*fRA+8); OPL.Put(iCAL+dest*fRT+dest*fRA+12) END
ELSE
CASE slack OF
| 1: x.typ := OPT.bytetyp; y.typ := OPT.bytetyp; Load(y, -1); Store(x, y); slack := 0
| 2: x.typ := OPT.inttyp; y.typ := OPT.inttyp; Load(y, -1); Store(x, y); slack := 0
| 4: x.typ := OPT.linttyp; y.typ := OPT.linttyp; Load(y, -1); Store(x, y); slack := 0
ELSE LoadAddr(x, -1); LoadAddr(y, -1); src := y.reg; dest := x.reg
END
END;
IF slack > 0 THEN
OPL.Put(iLSI+r1*fRT+src*fRA+slack*fNB); OPL.Put(iSTSI+r1*fRS+dest*fRA+slack*fNB)
END
ELSE
Base(x, -1); Base(y, -1);
DEC(x.offset, 4); DEC(y.offset, 4); LoadAddr(x, -1); LoadAddr(y, -1); src := y.reg; dest := x.reg;
r1 := OPL.GetTempRegs(2, {}); r2 := r1+1; Load(z, -1);
OPL.Put(iRLINM+z.reg*fRS+r1*fRA+29*fSH+3*fMB+31*fME+fREC); OPL.Put(iMTSPR+r1*fRS+spCTR*fSPR);
IF ~(src IN OPL.TempRegs) THEN src := OPL.GetTempR(); MoveReg(src, y.reg) END;
IF ~(dest IN OPL.TempRegs) THEN dest := OPL.GetTempR(); MoveReg(dest, x.reg) END;
IF ~aligned8 THEN
OPL.Put(iRLINM+z.reg*fRS+r2*fRA+29*fMB+31*fME); OPL.Put(iMTSPR+r2*fRS+spXER*fSPR)
END;
OPL.FreeTempR(z.reg); loopend := 0; PutBranchInstr(iBM, loopend); SetLabel(loop);
OPL.Put(iLU+r1*fRT+src*fRA+4); OPL.Put(iLU+r2*fRT+src*fRA+4);
OPL.Put(iSTU+r1*fRS+dest*fRA+4); OPL.Put(iSTU+r2*fRS+dest*fRA+4);
PutBranchInstr(iBCNTNZ, loop); SetLabel(loopend);
IF ~aligned8 THEN
slack := OPL.GetTempR(); OPL.Put(iCAL+slack*fRT+4);
OPL.Put(iLSX+r1*fRT+slack*fRA+src*fRB); OPL.Put(iSTSX+r1*fRS+slack*fRA+dest*fRB);
OPL.FreeTempR(slack)
END
END;
OPL.FreeTempR(r1); OPL.FreeTempR(r2); OPL.FreeTempR(src); OPL.FreeTempR(dest)
END Move;
PROCEDURE CommonDesign* (VAR x: OPL.Item);
BEGIN
IF x.mode IN {Var, VarPar, Based, Indexed} THEN
BaseOrInx(x, -1);
IF x.mode = Based THEN ShortBase(x, -1) END;
OPL.HoldTempR(x.reg);
IF x.mode = Indexed THEN OPL.HoldTempR(x.offset) END;
END
END CommonDesign;
PROCEDURE UnholdCommonDesign* (VAR x: OPL.Item);
BEGIN
IF x.mode IN {Based, Indexed} THEN OPL.UnholdTempR(x.reg);
IF x.mode = Indexed THEN OPL.UnholdTempR(x.offset) END;
END
END UnholdCommonDesign;
PROCEDURE^ Minus* (VAR x, y: OPL.Item; rt: LONGINT);
PROCEDURE^ Plus* (VAR x, y: OPL.Item; rt: LONGINT);
PROCEDURE Convert* (VAR x: OPL.Item; dtyp: OPT.Struct; rt: LONGINT; round: BOOLEAN);
VAR sform, dform, s, t: LONGINT; y, z: OPL.Item;
BEGIN
sform := x.typ^.form; dform := dtyp^.form; y.dreg := -1; z.dreg := -1;
IF sform # dform THEN
IF sform IN {Byte, Bool, Char, SInt, Int, LInt, Set, Pointer, NilTyp} THEN
IF dform IN {Byte, Bool, Char, SInt, Int, LInt, Set, Pointer, NilTyp} THEN Load(x, rt)
ELSE ASSERT(dform IN {Real, LReal});
Load(x, -1); MakeReg(x, -1);
IF IntToRealAddr = 0 THEN
OPL.AllocConst(IntToRealBlock, 16, IntToRealAddr, 8);
ASSERT((-32768 <= IntToRealAddr) & (IntToRealAddr <= 32767-16))
END;
s := x.reg; OPL.FreeTempR(s); t := OPL.GetTempR(); OPL.Put(iXORIU+t*fRA+s*fRS+8000H);
OPL.FreeTempR(t); OPL.Put(iST+t*fRS+SB*fRA+((IntToRealAddr+12) MOD LowWord));
x.mode := Based; x.reg := SB; x.offset := IntToRealAddr+8; x.typ := OPT.lrltyp;
y.mode := Based; y.reg := SB; y.offset := IntToRealAddr; y.typ := OPT.lrltyp; y.dreg := -1;
Minus(x, y, rt)
END
ELSIF ~(dform IN {Real, LReal}) THEN (* ENTIER *)
IF RealToIntAddr = 0 THEN OPL.AllocConst(RealToIntBlock, 8, RealToIntAddr, 8) END;
IF scratch < 0 THEN scratch := OPL.dsize; INC(OPL.dsize, 8) END;
t := OPL.GetTempF(); OPL.Put(iMFFS+t*fFRT); OPL.Put(iMTFSB1+30*fBT); OPL.Put(iMTFSB1+31*fBT);
y.mode := Based; y.reg := SB; y.offset := RealToIntAddr; y.typ := OPT.lrltyp; Load(x, -1); x.typ := OPT.lrltyp;
Plus(y, x, -1);
z.mode := Based; z.reg := SB; z.offset := scratch; z.typ := OPT.lrltyp; Store(z, y);
x.mode := Based; x.reg := SB;
OPL.Put(iMTFSF+1*fFLM+t*fFRB); OPL.FreeTempF(t);
IF dtyp^.form IN {Byte, Bool, Char, SInt} THEN x.offset := scratch+7
ELSIF dtyp^.form = Int THEN x.offset := scratch+6
ELSE x.offset := scratch+4
END;
x.typ := dtyp; Load(x, rt)
ELSE (* conversion between Real and LReal *)
Load(x, rt);
IF round & (sform = LReal) THEN ASSERT(dform = Real);
OPL.FreeTempF(x.reg); rt := CheckF(rt); OPL.Put(iFRSP+rt*fFRT+x.reg*fFRB); x.reg := rt; x.typ := OPT.realtyp
END
END
END;
x.typ := dtyp
END Convert;
PROCEDURE Field* (VAR x: OPL.Item; offset, rt: LONGINT);
BEGIN
IF offset = 0 THEN BaseOrInx(x, rt) ELSE Base(x, rt); INC(x.offset, offset) END;
ASSERT(x.mode IN {Based, Indexed});
END Field;
PROCEDURE^ Times* (VAR x, y: OPL.Item; rt: LONGINT);
PROCEDURE^ Ash* (VAR x, y: OPL.Item; rt: LONGINT);
PROCEDURE TypeSize* (VAR x: OPL.Item; typ: OPT.Struct; rt: LONGINT);
VAR y: OPL.Item; dmode: SHORTINT; dreg, doff, s: LONGINT;
BEGIN
IF typ^.comp # DynArr THEN
x.mode := Con; x.typ := OPT.linttyp; x.offset := typ^.size
ELSE
dmode := x.dmode; dreg := x.dreg; doff := x.adr; x.mode := dmode; x.typ := OPT.linttyp;
IF dmode = Reg THEN x.reg := dreg+typ^.offset DIV 4 ELSE x.reg := dreg; x.offset := doff+typ^.offset END;
typ := typ^.BaseTyp; x.dreg := -1;
WHILE typ^.comp = DynArr DO
y.mode := dmode; y.typ := OPT.linttyp; y.dreg := -1;
IF dmode = Reg THEN y.reg := dreg+typ^.offset DIV 4 ELSE y.reg := dreg; y.offset := doff+typ^.offset END;
s := rt; typ := typ^.BaseTyp;
IF (typ^.comp = DynArr) OR (typ^.size > 1) THEN s := -1 END;
Times(x, y, s)
END;
s := typ^.size;
IF s > 1 THEN
y.mode := Con; y.dreg := -1;
IF SYSTEM.VAL(SET, s)*SYSTEM.VAL(SET, s-1) = {} THEN
y.offset := 31-CNTLZ(s); Ash(x, y, rt)
ELSE
y.offset := s; Times(x, y, rt)
END
END;
x.dreg := SHORT(SHORT(dreg))
END
END TypeSize;
PROCEDURE MulOrShift (VAR x, y: OPL.Item; rt: LONGINT);
VAR n: LONGINT; z: OPL.Item;
BEGIN
ASSERT(y.mode = Con);
n := y.offset;
IF x.mode = Con THEN x.offset := x.offset * n
ELSIF n > 1 THEN
IF SYSTEM.VAL(SET, n)*SYSTEM.VAL(SET, n-1) = {} THEN z := y; z.offset := 31-CNTLZ(n); Ash(x, z, rt)
ELSE Times(x, y, rt)
END
END
END MulOrShift;
PROCEDURE MulDim* (VAR nofel, len: OPL.Item; rt: LONGINT);
VAR y: OPL.Item;
BEGIN
IF nofel.mode = Con THEN
IF len.mode = Con THEN nofel.offset := nofel.offset*len.offset
ELSE y := len; MulOrShift(y, nofel, rt); nofel := y
END
ELSE
IF len.mode = Con THEN MulOrShift(nofel, len, rt)
ELSE Times(nofel, len, rt)
END
END
END MulDim;
PROCEDURE GenDimTrap* (VAR len: OPL.Item);
BEGIN
IF inxchk IN options THEN Load(len, -1); OPL.SetTrap(DimTrap); OPL.Put(iTI+tSLE*fTO+len.reg*fRA) END
END GenDimTrap;
PROCEDURE Index* (VAR x, y: OPL.Item; rt: LONGINT);
VAR t, n, elemSize, inx: LONGINT; mode: SHORTINT; basedRes: BOOLEAN; v, z: OPL.Item;
BEGIN
z.dreg := -1;
IF x.typ^.comp = Array THEN
BaseOrInx(x, -1); elemSize := x.typ^.BaseTyp^.size;
IF y.mode = Con THEN Field(x, y.offset*elemSize, rt)
ELSE
IF x.mode = Indexed THEN ReduceIndex(x, x.offset, -1); x.offset := 0; x.mode := Based END;
basedRes := x.offset # 0; Load(y, -1); MakeReg(y, -1); t := rt; IF basedRes THEN t := -1 END;
IF inxchk IN options THEN
n := x.typ^.n; inx := y.reg;
IF n < 7FFFH THEN OPL.SetTrap(IndexCheck); OPL.Put(iTI+tUGE*fTO+inx*fRA+n)
ELSE
z.mode := Con; z.typ := OPT.linttyp; z.offset := n; Load(z, -1); t := z.reg; OPL.FreeTempR(t);
OPL.SetTrap(IndexCheck); OPL.Put(iT+tUGE*fTO+inx*fRA+t*fRB)
END
END;
z.mode := Con; z.typ := OPT.linttyp; z.offset := elemSize; MulOrShift(y, z, t);
IF basedRes THEN ReduceIndex(x, y.reg, rt) ELSE x.mode := Indexed; x.offset := y.reg END
END
ELSE (* DynArr *)
IF (y.mode = Con) & (y.offset = 0) THEN Field(x, 0, rt)
ELSE
IF x.mode = Indexed THEN ReduceIndex(x, x.offset, -1); x.mode := Based; x.offset := 0 END;
basedRes := x.offset # 0;
IF inxchk IN options THEN
v := y; IF (v.mode # Con) OR (v.offset >= 7FFFH) THEN Load(v, -1); MakeReg(v, -1) END;
mode := x.dmode; z.mode := mode; z.typ := OPT.linttyp;
IF mode = Reg THEN z.reg := x.dreg+x.typ^.offset DIV 4
ELSE z.reg := x.dreg; z.offset := x.adr+x.typ^.offset; Load(z, -1)
END;
IF v.mode = Con THEN OPL.SetTrap(IndexCheck); OPL.Put(iTI+tULE*fTO+z.reg*fRA+v.offset)
ELSE OPL.SetTrap(IndexCheck); OPL.Put(iT+tUGE*fTO+v.reg*fRA+z.reg*fRB)
END;
OPL.FreeTempR(z.reg);
IF (y.mode # Reg) & (v.mode = Reg) THEN
IF (y.mode = Con) & (SYSTEM.VAL(SET, y.offset)*SYSTEM.VAL(SET, y.offset-1) = {}) THEN
OPL.FreeTempR(v.reg)
ELSE y.mode := Reg; y.reg := v.reg
END
END
END;
v := x; TypeSize(v, v.typ^.BaseTyp, -1); ASSERT(x.mode = Based);
v.dreg := -1;
IF v.mode = Con THEN
IF y.mode = Con THEN y.offset := y.offset*v.offset ELSE MulOrShift(y, v, -1) END
ELSE
IF y.mode = Con THEN MulOrShift(v, y, -1); y := v ELSE Times(y, v, -1) END
END;
IF ~(y.mode IN {Con, Reg}) THEN Load(y, -1); MakeReg(y, -1) END;
IF basedRes THEN
IF y.mode = Con THEN INC(x.offset, y.offset) ELSE ReduceIndex(x, y.reg, rt) END
ELSE
IF y.mode = Con THEN x.offset := y.offset ELSE x.mode := Indexed; x.offset := y.reg END
END
END
END
END Index;
PROCEDURE Deref* (VAR x: OPL.Item; rt: LONGINT);
VAR btyp: OPT.Struct;
BEGIN
ASSERT(x.typ.form = Pointer);
Load(x, rt);
x.mode := Based; x.offset := 0;
btyp := x.typ.BaseTyp;
IF btyp.comp = Array THEN
REPEAT btyp := btyp.BaseTyp UNTIL btyp.comp # Array;
IF (btyp.comp = Record) OR (btyp.form = Pointer) THEN x.offset := 16 END
END;
IF nilchk IN options THEN OPL.SetTrap(NilTrap); OPL.Put(iTI+tSLE*fTO+x.reg*fRA) END (* tSLE statt tEQ *)
(* IF nilchk IN options THEN OPL.SetTrap(NilTrap); OPL.Put(iTI+tEQ*fTO+x.reg*fRA) END *)
END Deref;
PROCEDURE DynArrItem* (VAR x: OPL.Item; rt: LONGINT);
VAR dreg, doff, nofdim: LONGINT; typ: OPT.Struct; wasVar: BOOLEAN;
BEGIN
IF x.dmode IN {Reg, Var, VarPar} THEN (* normal dynamic arrays *) (* << mmb 15.11.91, temp fix for DynArr *)
IF x.mode = Reg THEN
x.dreg := SHORT(SHORT(x.reg)); x.mode := Based; x.offset := 0
ELSE
Base(x, -1); dreg := x.dreg;
IF dreg = rt THEN
dreg := OPL.GetTempR(); MoveReg(dreg, rt)
END;
x.dreg := SHORT(SHORT(dreg));
END
ELSE
wasVar := x.mode IN {Var, VarPar};
IF x.mode = VarPar THEN x.mode := Var END;
Base(x, -1); dreg := x.reg;
IF wasVar THEN
doff := x.offset; x.typ := OPT.linttyp; Load(x, rt); x.mode := Based; x.offset := 0
ELSE
doff := 8;
nofdim := 0; typ := x.typ; REPEAT INC(nofdim); typ := typ^.BaseTyp UNTIL typ^.comp # DynArr;
ASSERT(x.offset = 0);
x.offset := (nofdim DIV 2)*8+16
END;
x.dmode := Based; x.dreg := SHORT(SHORT(dreg)); OPL.HoldTempR(dreg); x.adr := doff
END
END DynArrItem;
PROCEDURE^ Compare* (VAR x, y: OPL.Item; subcl: INTEGER);
PROCEDURE TypTest* (VAR x: OPL.Item; typ: OPT.Struct; guard, equal, varrec: BOOLEAN);
VAR y, z: OPL.Item; h1, h2: LONGINT;
BEGIN
ASSERT(x.typ^.form = typ^.form);
IF ~guard OR (typchk IN options) THEN
IF guard THEN
h1 := -1; h2 := -1; z := x;
IF z.mode IN {Reg, RegSI, Based, Indexed} THEN h1 := z.reg; OPL.HoldTempR(h1) END;
IF z.mode = Indexed THEN h2 := z.offset; OPL.HoldTempR(h2) END
END;
IF ~varrec THEN
IF typ^.form = Pointer THEN Load(x, -1); x.mode := Based; x.offset := -4
ELSE Base(x, -1); DEC(x.offset, 4)
END;
x.typ := OPT.linttyp; Load(x, -1);
IF typ^.form = Pointer THEN typ := typ^.BaseTyp END
ELSE (* VarPar *)
IF x.mode = Based THEN
INC(x.reg); x.mode := Reg; x.typ := OPT.linttyp
ELSE
x.reg := FindFP(OPL.level, x.mnolev, -1); x.mode := Based; x.typ := OPT.linttyp; INC(x.offset, 4); Load(x, -1)
END
END;
y.mode := Var; y.mnolev := -typ^.mno; y.offset := typ^.tdadr; y.dreg := -1; y.typ := OPT.linttyp; Load(y, -1);
IF ~equal THEN x.mode := Based; x.offset := -8-typ^.extlev*4; Load(x, -1) END;
IF guard THEN
OPL.SetTrap(TypeGuard); OPL.FreeTempR(x.reg); OPL.FreeTempR(y.reg);
OPL.Put(iT+tNEQ*fTO+x.reg*fRA+y.reg*fRB); x := z;
IF h1 >= 0 THEN OPL.UnholdTempR(h1) END;
IF h2 >= 0 THEN OPL.UnholdTempR(h2) END
ELSE
Compare(x, y, eql)
END
END
END TypTest;
PROCEDURE RealUnary (op: LONGINT; VAR x: OPL.Item; rt: LONGINT);
VAR s: LONGINT;
BEGIN
Load(x, -1); s := x.reg; OPL.FreeTempF(s); rt := CheckF(rt); OPL.Put(op+rt*fFRT+s*fFRB); x.reg := rt
END RealUnary;
PROCEDURE FAddOp (op: LONGINT; VAR x, y: OPL.Item; rt: LONGINT);
VAR s1, s2: LONGINT;
BEGIN
Load(x, -1); Load(y, -1); s1 := x.reg; s2 := y.reg; OPL.FreeTempF(s1); OPL.FreeTempF(s2); rt := CheckF(rt);
OPL.Put(op+rt*fFRT+s1*fFRA+s2*fFRB); x.reg := rt
END FAddOp;
PROCEDURE FMulOp (op: LONGINT; VAR x, y: OPL.Item; rt: LONGINT);
VAR s1, s2: LONGINT;
BEGIN
Load(x, -1); Load(y, -1); s1 := x.reg; s2 := y.reg; OPL.FreeTempF(s1); OPL.FreeTempF(s2); rt := CheckF(rt);
OPL.Put(op+rt*fFRT+s1*fFRA+s2*fFRC); x.reg := rt
END FMulOp;
PROCEDURE FMulAddOp (op: LONGINT; VAR x, y, z: OPL.Item; rt: LONGINT);
VAR s1, s2, s3: LONGINT;
BEGIN
Load(x, -1); Load(y, -1); Load(z, -1); s1 := x.reg; s2 := y.reg; s3 := z.reg;
OPL.FreeTempF(s1); OPL.FreeTempF(s2); OPL.FreeTempF(s3); rt := CheckF(rt);
OPL.Put(op+rt*fFRT+s1*fFRA+s2*fFRC+s3*fFRB); x.reg := rt
END FMulAddOp;
PROCEDURE IntUnary (op: LONGINT; VAR x: OPL.Item; rt: LONGINT);
VAR s: LONGINT;
BEGIN
Load(x, -1); MakeReg(x, -1); s := x.reg; OPL.FreeTempR(s); rt := CheckR(rt); OPL.Put(op+rt*fRT+s*fRA); x.reg := rt
END IntUnary;
PROCEDURE IntBinary (op: LONGINT; VAR x, y: OPL.Item; rt: LONGINT);
VAR s1, s2: LONGINT;
BEGIN
Load(x, -1); MakeReg(x, -1); Load(y, -1); MakeReg(y, -1); s1 := x.reg; s2 := y.reg;
OPL.FreeTempR(s1); OPL.FreeTempR(s2); rt := CheckR(rt); OPL.Put(op+rt*fRT+s1*fRA+s2*fRB); x.reg := rt
END IntBinary;
PROCEDURE IntAddImm (VAR x, y: OPL.Item; rt: LONGINT);
VAR s, t, l, u: LONGINT;
BEGIN
ASSERT(y.mode = Con);
Load(x, -1); MakeReg(x, -1); s := x.reg; OPL.FreeTempR(s);
u := y.offset; l := u MOD LowWord; u := (SYSTEM.LSH(u, -16)+SYSTEM.LSH(l, -15)) MOD LowWord;
IF u = 0 THEN rt := CheckR(rt); OPL.Put(iAI+rt*fRT+s*fRA+l)
ELSIF l = 0 THEN rt := CheckR(rt); OPL.Put(iCAU+rt*fRT+s*fRA+u)
ELSE t := OPL.GetTempR(); OPL.FreeTempR(t); OPL.Put(iCAU+t*fRT+s*fRA+u);
rt := CheckR(rt); OPL.Put(iCAL+rt*fRT+t*fRA+l)
END;
x.reg := rt
END IntAddImm;
PROCEDURE IntSubImm (VAR x, y: OPL.Item; rt: LONGINT); (* x := x-y *)
VAR s, u, l: LONGINT;
BEGIN
ASSERT(x.mode = Con);
u := x.offset; l := u MOD LowWord; u := (SYSTEM.LSH(u, -16)+SYSTEM.LSH(l, -15)) MOD LowWord;
IF u # 0 THEN IntBinary(iSF, y, x, rt); x.mode := y.mode; x.reg := y.reg; x.offset := y.offset
ELSE Load(y, -1); MakeReg(y, -1); s := y.reg; OPL.FreeTempR(s); rt := CheckR(rt);
OPL.Put(iSFI+rt*fRT+s*fRA+l); x.mode := Reg; x.reg := rt
END
END IntSubImm;
PROCEDURE IntMulImm (VAR x, y: OPL.Item; rt: LONGINT);
VAR s, u, l: LONGINT;
BEGIN
ASSERT(y.mode = Con);
u := y.offset; l := u MOD LowWord; u := (SYSTEM.LSH(u, -16)+SYSTEM.LSH(l, -15)) MOD LowWord;
IF u # 0 THEN IntBinary(iMULS, x, y, rt)
ELSE Load(x, -1); MakeReg(x, -1); s := x.reg; OPL.FreeTempR(s); rt := CheckR(rt);
OPL.Put(iMULI+rt*fRT+s*fRA+l); x.reg := rt
END
END IntMulImm;
PROCEDURE IntCmp (VAR x, y: OPL.Item): LONGINT;
VAR s1, s2, f: LONGINT;
BEGIN
Load(x, -1); MakeReg(x, -1); Load(y, -1); MakeReg(y, -1); s1 := x.reg; s2 := y.reg;
OPL.FreeTempR(s1); OPL.FreeTempR(s2); f := OPL.GetTempCRF(); OPL.Put(iCMP+f*fBF+s1*fRA+s2*fRB);
RETURN f
END IntCmp;
PROCEDURE IntCmpImm (VAR x, y: OPL.Item): LONGINT;
VAR s1, s2, f: LONGINT;
BEGIN
ASSERT(y.mode = Con);
s2 := y.offset;
IF (-32767 < s2) & (s2 < 32768) THEN
Load(x, -1); MakeReg(x, -1); s1 := x.reg; OPL.FreeTempR(s1); f := OPL.GetTempCRF();
OPL.Put(iCMPI+f*fBF+s1*fRA+(s2 MOD LowWord)); RETURN f
ELSE RETURN IntCmp(x, y)
END
END IntCmpImm;
PROCEDURE SetBinary (op: LONGINT; VAR x, y: OPL.Item; rt: LONGINT);
VAR s1, s2: LONGINT;
BEGIN
Load(x, -1); Load(y, -1); s1 := x.reg; s2 := y.reg; x.mode := Reg;
OPL.FreeTempR(s1); OPL.FreeTempR(s2); rt := CheckR(rt); OPL.Put(op+rt*fRA+s1*fRS+s2*fRB); x.reg := rt
END SetBinary;
PROCEDURE SetInterImm (VAR x, y: OPL.Item; rt: LONGINT);
VAR u, l, s, f: LONGINT;
BEGIN
u := y.offset; l := u MOD LowWord; u := SYSTEM.LSH(u, -16); Load(x, -1); s := x.reg; f := OPL.GetCRF0();
IF (u = 0) & (f = 0) THEN OPL.FreeTempR(s); rt := CheckR(rt); OPL.Put(iANDIL+rt*fRA+s*fRS+l); x.reg := rt
ELSIF (l = 0) & (f = 0) THEN OPL.FreeTempR(s); rt := CheckR(rt); OPL.Put(iANDIU+rt*fRA+s*fRS+u); x.reg := rt
ELSE SetBinary(iAND, x, y, rt)
END;
f := f*4; OPL.FreeTempCRBs({f..f+3})
(* here, an additional optimization can be made that uses the RLINM instruction for contiguous masks *)
END SetInterImm;
PROCEDURE SetSymImm (iop: LONGINT; VAR x, y: OPL.Item; rt: LONGINT);
VAR u, l, s, t: LONGINT;
BEGIN
ASSERT(y.mode = Con);
u := y.offset; l := u MOD LowWord; u := SYSTEM.LSH(u, -16);
Load(x, -1); MakeReg(x, -1); s := x.reg; OPL.FreeTempR(s);
IF u = 0 THEN rt := CheckR(rt); OPL.Put(iop+rt*fRA+s*fRS+l)
ELSE
IF l # 0 THEN t := OPL.GetTempR(); OPL.FreeTempR(t); OPL.Put(iop+t*fRA+s*fRS+l); s := t END;
rt := CheckR(rt); OPL.Put(iop+iUPPER+rt*fRA+s*fRS+u)
END;
x.reg := rt
END SetSymImm;
PROCEDURE SetRange* (VAR x, y: OPL.Item; rt: LONGINT);
VAR s1, s2: LONGINT;
BEGIN
Load(x, -1); Load(y, -1); s1 := x.reg; s2 := y.reg; OPL.FreeTempR(s1); OPL.FreeTempR(s2);
rt := CheckR(rt); OPL.Put(iMASKG+rt*fRA+s1*fRS+s2*fRB); x.reg := rt
END SetRange;
PROCEDURE SetElem* (VAR x: OPL.Item; rt: LONGINT);
VAR s: LONGINT;
BEGIN
Load(x, -1); s := x.reg; OPL.FreeTempR(s); rt := CheckR(rt); OPL.Put(iMASKG+rt*fRA+s*fRS+s*fRB); x.reg := rt
END SetElem;
PROCEDURE Not* (VAR x: OPL.Item; rt: LONGINT);
VAR s: LONGINT; l: OPL.Label;
BEGIN
l := x.Tjmp; x.Tjmp := x.Fjmp; x.Fjmp := l;
IF x.mode = Cond THEN x.reg := -1-x.reg
ELSE Load(x, -1); s := x.reg; OPL.FreeTempR(s); rt := CheckR(rt); OPL.Put(iSFI+rt*fRT+s*fRA+1); x.reg := rt
END
END Not;
PROCEDURE Neg* (VAR x: OPL.Item; rt: LONGINT);
BEGIN
CASE x.typ^.form OF
SInt, Int, LInt: IntUnary(iNEG, x, rt)
| Real, LReal: RealUnary(iFNEG, x, rt)
| Set:
IF x.mode = RegSI THEN x.mode := Reg END;
IntUnary(iNOT, x, rt)
END
END Neg;
PROCEDURE Abs* (VAR x: OPL.Item; rt: LONGINT);
VAR s, t0, t1: LONGINT;
BEGIN
CASE x.typ^.form OF
SInt, Int, LInt:
IF powerpc IN options THEN
Load(x, -1); MakeReg(x, -1);
s := x.reg; t0 := OPL.GetTempR();
OPL.Put(iSRAI+t0*fRA+s*fRS+24*fSH);
OPL.FreeTempR(s); t1 := OPL.GetTempR();
OPL.Put(iXOR+t1*fRA+t0*fRS+s*fRB);
OPL.FreeTempR(t0); OPL.FreeTempR(t1);
rt := CheckR(rt);
OPL.Put(iSF+rt*fRT+t0*fRA+t1*fRB);
x.reg := rt
ELSE
IntUnary(iABS, x, rt)
END
| Real, LReal: RealUnary(iFABS, x, rt)
END
END Abs;
PROCEDURE Cap* (VAR x: OPL.Item; rt: LONGINT);
BEGIN SetInterImm(x, CAPmask, rt)
END Cap;
PROCEDURE VarShift (rop: LONGINT; VAR x, y: OPL.Item; rt: LONGINT): LONGINT;
VAR s1, s2, t: LONGINT; l: OPL.Label;
BEGIN
ASSERT(x.mode = Reg);
s1 := x.reg; Load(y, -1); MakeReg(y, -1); s2 := y.reg; y.Fjmp := 0;
Compare(y, zero, lss); OPL.FreeTempR(s1); OPL.FreeTempR(s2); PutCondBranch(y, FALSE);
t := OPL.GetTempR(); OPL.FreeTempR(t); rt := CheckR(rt); OPL.Put(iABS+t*fRT+s2*fRA);
OPL.Put(rop+rt*fRA+s1*fRS+t*fRB); l := 0; PutBranch(l); SetLabel(y.Fjmp);
OPL.Put(iSL+rt*fRA+s1*fRS+s2*fRB); SetLabel(l);
RETURN rt
END VarShift;
PROCEDURE Ash* (VAR x, y: OPL.Item; rt: LONGINT);
VAR sh, s, t: LONGINT;
BEGIN
Load(x, -1);
IF y.mode = Con THEN
sh := y.offset; s := x.reg; OPL.FreeTempR(s);
IF x.mode = RegSI THEN
IF sh >= 24 THEN
sh := sh MOD 32; rt := CheckR(rt); OPL.Put(iRLINM+rt*fRA+s*fRS+sh*fSH+(31-sh)*fME)
ELSE
sh := IMIN(24-sh, 31); t := OPL.GetTempR(); OPL.FreeTempR(t);
OPL.Put(iRLINM+t*fRA+s*fRS+24*fSH+8*fME); rt := CheckR(rt); OPL.Put(iSRAI+rt*fRA+t*fRS+sh*fSH)
END;
x.mode := Reg
ELSE rt := CheckR(rt);
IF sh < 0 THEN OPL.Put(iSRAI+rt*fRA+s*fRS+((-sh) MOD 32)*fSH)
ELSE sh := sh MOD 32; OPL.Put(iRLINM+rt*fRA+s*fRS+sh*fSH+(31-sh)*fME)
END
END
ELSE rt := VarShift(iSRA, x, y, rt)
END;
x.reg := rt
END Ash;
PROCEDURE Times* (VAR x, y: OPL.Item; rt: LONGINT);
BEGIN
CASE x.typ^.form OF
SInt, Int, LInt:
IF x.mode = Con THEN IntMulImm(y, x, rt); x.mode := y.mode; x.reg := y.reg; x.offset := y.offset
ELSIF y.mode = Con THEN IntMulImm(x, y, rt)
ELSE IntBinary(iMULS, x, y, rt)
END
| Real:
IF powerpc IN options THEN FMulOp(iFMULS, x, y, rt) ELSE FMulOp(iFM, x, y, rt) END
| LReal: FMulOp(iFM, x, y, rt)
| Set:
IF x.mode = Con THEN SetInterImm(y, x, rt); x.mode := y.mode; x.reg := y.reg; x.offset := y.offset
ELSIF y.mode = Con THEN SetInterImm(x, y, rt)
ELSE SetBinary(iAND, x, y, rt)
END
END;
END Times;
PROCEDURE Div* (VAR x, y: OPL.Item; rt: LONGINT);
VAR s1, s2: LONGINT; z: OPL.Item; xoptb, xoptc, yopt: BOOLEAN;
BEGIN
ASSERT(x.typ^.form IN {SInt, Int, LInt});
xoptb := x.mode = Con; yopt := y.mode = Con; xoptc := FALSE;
IF xoptb THEN xoptc := x.offset >= 0 END;
IF yopt & (y.offset <= 0) THEN OPM.err(301) END;
Load(x, -1); MakeReg(x, -1); Load(y, -1); MakeReg(y, -1); s1 := x.reg; s2 := y.reg;
OPL.FreeTempR(s1); OPL.FreeTempR(s2); rt := CheckR(rt);
IF ~yopt THEN OPL.SetTrap(DivideTrap); OPL.Put(iTI+tSLE*fTO+s2*fRA) END;
OPL.Put(iDIVS+rt*fRT+s1*fRA+s2*fRB+fREC);
IF ~xoptb THEN z.mode := Cond; z.reg := -1-bLT; z.Tjmp := 0; PutCondBranch(z, TRUE) END;
IF ~xoptc THEN OPL.Put(iAI+rt*fRT+rt*fRA+((-1) MOD LowWord)) END;
IF ~xoptb THEN SetLabel(z.Tjmp) END;
x.reg := rt
END Div;
PROCEDURE Slash* (VAR x, y: OPL.Item; rt: LONGINT);
BEGIN
CASE x.typ^.form OF
Real:
IF powerpc IN options THEN FAddOp(iFDIVS, x, y, rt) ELSE FAddOp(iFD, x, y, rt) END
| LReal: FAddOp(iFD, x, y, rt)
| Set:
IF x.mode = Con THEN SetSymImm(iXORIL, y, x, rt); x.mode := y.mode; x.reg := y.reg; x.offset := y.offset
ELSIF y.mode = Con THEN SetSymImm(iXORIL, x, y, rt)
ELSE SetBinary(iXOR, x, y, rt)
END
END
END Slash;
PROCEDURE Mod* (VAR x, y: OPL.Item; rt: LONGINT);
VAR s1, s2, t, imm: LONGINT; z: OPL.Item; xoptb, xoptc, yopt, ysimm: BOOLEAN;
BEGIN
ASSERT(x.typ^.form IN {SInt, Int, LInt});
xoptb := x.mode = Con; yopt := y.mode = Con; xoptc := FALSE; ysimm := FALSE;
IF xoptb THEN xoptc := x.offset > 0 END;
IF yopt THEN imm := y.offset;
IF imm <= 0 THEN OPM.err(301) ELSE ysimm := imm < 32767 END
END;
Load(x, -1); MakeReg(x, -1); Load(y, -1); MakeReg(y, -1); s1 := x.reg; s2 := y.reg; OPL.FreeTempR(s1);
IF ~yopt THEN OPL.SetTrap(DivideTrap); OPL.Put(iTI+tSLE*fTO+s2*fRA) END;
OPL.Put(iDIVS+s1*fRA+s2*fRB+fREC); rt := CheckR(rt); OPL.FreeTempR(s2);
IF ~xoptc & ~ysimm & (rt = s2) THEN
t := OPL.GetTempR(); MoveReg(t, s2); s2 := t; OPL.FreeTempR(t)
END;
OPL.Put(iMFSPR+rt*fRT+spMQ*fSPR);
IF ~xoptb THEN z.mode := Cond; z.reg := -1-bLT; z.Tjmp := 0; PutCondBranch(z, TRUE) END;
IF ~xoptc THEN
IF ysimm THEN OPL.Put(iAI+rt*fRT+rt*fRA+(imm MOD LowWord))
ELSE OPL.Put(iA+rt*fRT+rt*fRA+s2*fRB)
END
END;
IF ~xoptb THEN SetLabel(z.Tjmp) END;
x.reg := rt
END Mod;
PROCEDURE Plus* (VAR x, y: OPL.Item; rt: LONGINT);
BEGIN
CASE x.typ^.form OF
SInt, Int, LInt:
IF x.mode = Con THEN IntAddImm(y, x, rt); x.mode := y.mode; x.reg := y.reg; x.offset := y.offset
ELSIF y.mode = Con THEN IntAddImm(x, y, rt)
ELSE IntBinary(iCAX, x, y, rt)
END
| Real:
IF powerpc IN options THEN FAddOp(iFADDS, x, y, rt) ELSE FAddOp(iFA, x, y, rt) END
| LReal: FAddOp(iFA, x, y, rt)
| Set:
IF x.mode = Con THEN SetSymImm(iORIL, y, x, rt); x.mode := y.mode; x.reg := y.reg; x.offset := y.offset
ELSIF y.mode = Con THEN SetSymImm(iORIL, x, y, rt)
ELSE SetBinary(iOR, x, y, rt)
END
END
END Plus;
PROCEDURE Minus* (VAR x, y: OPL.Item; rt: LONGINT);
BEGIN
CASE x.typ^.form OF
SInt, Int, LInt:
IF x.mode = Con THEN IntSubImm(x, y, rt)
ELSIF y.mode = Con THEN y.offset := -y.offset; IntAddImm(x, y, rt)
ELSE IntBinary(iSF, y, x, rt); x.mode := y.mode; x.reg := y.reg; x.offset := y.offset
END
| Real:
IF powerpc IN options THEN FAddOp(iFSUBS, x, y, rt) ELSE FAddOp(iFS, x, y, rt) END
| LReal: FAddOp(iFS, x, y, rt)
| Set:
IF y.mode = Con THEN y.offset := -1-y.offset; SetInterImm(x, y, rt)
(* if x.mode = Con, an optimization could be to translate to (-y) MASK x, if the number of masks is 1 in x *)
ELSE SetBinary(iANDC, x, y, rt)
END
END
END Minus;
PROCEDURE MulAdd* (VAR x, y, z: OPL.Item; rt: LONGINT);
BEGIN
IF (powerpc IN options) & (x.typ^.form = Real) THEN FMulAddOp(iFMADDS, x, y, z, rt)
ELSE FMulAddOp(iFMA, x, y, z, rt)
END
END MulAdd;
PROCEDURE MulSub* (VAR x, y, z: OPL.Item; rt: LONGINT; invert: BOOLEAN);
BEGIN
IF (powerpc IN options) & (x.typ^.form = Real) THEN
IF invert THEN FMulAddOp(iFNMSUBS, x, y, z, rt) ELSE FMulAddOp(iFMSUBS, x, y, z, rt) END
ELSE
IF invert THEN FMulAddOp(iFNMS, x, y, z, rt) ELSE FMulAddOp(iFMS, x, y, z, rt) END
END
END MulSub;
PROCEDURE In* (VAR x, y: OPL.Item);
VAR s1, s2, t, crf, ropt: LONGINT;
BEGIN
ASSERT((x.typ^.form IN {SInt, Int, LInt}) & (y.typ^.form = Set));
Load(y, -1); IF y.mode = RegSI THEN y.mode := Reg END;
s2 := y.reg;
crf := OPL.GetCRF0();
IF crf = 0 THEN ropt := fREC ELSE OPL.FreeTempCRBs({crf*4..crf*4+3}); ropt := 0 END;
IF x.mode = Con THEN
OPL.FreeTempR(s2); t := OPL.GetTempR();
OPL.Put(iRLINM+t*fRA+s2*fRS+(x.offset MOD 32)*fSH+ropt)
ELSE
Load(x, -1); s1 := x.reg; OPL.FreeTempR(s1); OPL.FreeTempR(s2); t := OPL.GetTempR();
OPL.Put(iRLNM+t*fRA+s2*fRS+s1*fRB+ropt)
END;
IF crf = 0 THEN
x.mode := Cond; x.reg := -1-bEQ; OPL.FreeTempR(t)
ELSE
x.mode := Reg; x.reg := t
END
END In;
PROCEDURE Odd* (VAR x: OPL.Item);
VAR z: OPL.Item;
BEGIN Load(x, -1); MakeReg(x, -1);
z := zero; z.offset := 31; x.typ := OPT.settyp; In(z, x); x.mode := z.mode; x.reg := z.reg; x.offset := z.offset
END Odd;
PROCEDURE SYSaddr* (VAR x: OPL.Item; rt: LONGINT);
BEGIN LoadAddr(x, rt)
END SYSaddr;
PROCEDURE SYSval* (VAR x: OPL.Item; sform, dform: INTEGER);
VAR y: OPL.Item; adr: LONGINT;
BEGIN
IF x.mode = Cond THEN CondToReg(x, -1) END;
IF (x.mode = Con) & (dform IN {Real, LReal}) THEN
OPL.AllocConst(x.offset, 4, adr, 4);
(* note: for LReal, the lower 32 bits are undefined *)
x.mode := Based; x.reg := SB; x.offset := adr
ELSIF (x.mode IN {Reg, FReg}) & ((sform IN {Real, LReal}) # (dform IN {Real, LReal})) THEN
IF scratch < 0 THEN scratch := OPL.dsize; INC(OPL.dsize, 8) END;
y.mode := Based; y.reg := SB; y.offset := scratch; y.typ := x.typ; y.dreg := -1; Store(y, x);
x.mode := y.mode; x.reg := y.reg; x.offset := y.offset
END
END SYSval;
PROCEDURE SYSlsh* (VAR x, y: OPL.Item; rt: LONGINT);
VAR s1, s2: LONGINT;
BEGIN
Load(x, -1); MakeReg(x, -1); s1 := x.reg;
(* the case where x.mode = RegSI may be optimized here *)
IF y.mode = Con THEN
s2 := y.offset; OPL.FreeTempR(s1); rt := CheckR(rt);
IF x.typ.form = Set THEN s2 := -s2 END;
IF s2 < 0 THEN OPL.Put(iRLINM+rt*fRA+s1*fRS+(s2 MOD 32)*fSH+(-s2)*fMB+31*fME)
ELSE OPL.Put(iRLINM+rt*fRA+s1*fRS+(s2 MOD 32)*fSH+((31-s2) MOD 32)*fME)
END
ELSE
IF x.typ.form = Set THEN Neg(y, -1) END;
rt := VarShift(iSR, x, y, rt)
END;
x.reg := rt
END SYSlsh;
PROCEDURE SYSrot* (VAR x, y: OPL.Item; rt: LONGINT);
VAR s, t, mb: LONGINT;
BEGIN
Load(x, -1);
CASE x.typ^.form OF
Byte, Char, SInt:
s := x.reg; OPL.Put(iRLIMI+s*fRA+s*fRS+8*fSH+16*fMB+23*fME);
OPL.Put(iRLIMI+s*fRA+s*fRS+16*fSH+15*fME); mb := 24
| Int:
MakeReg(x, -1); s := x.reg; OPL.Put(iRLIMI+s*fRA+s*fRS+16*fSH+15*fME); mb := 16
| LInt, Set:
MakeReg(x, -1); s := x.reg; mb := 0
END;
IF y.mode # Con THEN
IF x.typ.form = Set THEN Neg(y, -1) END;
Load(y, -1); OPL.FreeTempR(s); t := y.reg; OPL.FreeTempR(t); rt := CheckR(rt);
OPL.Put(iRLNM+rt*fRA+s*fRS+t*fRB+mb*fMB+31*fME)
ELSE
t := y.offset; OPL.FreeTempR(s); rt := CheckR(rt);
IF x.typ.form = Set THEN t := -t END;
OPL.Put(iRLINM+rt*fRA+s*fRS+(t MOD 32)*fSH+mb*fMB+31*fME)
END;
x.reg := rt
END SYSrot;
PROCEDURE^ Assign* (VAR x, y: OPL.Item);
PROCEDURE SYSget* (VAR x, z, y: OPL.Item);
BEGIN
Load(x, -1); MakeReg(x, -1);
IF z.mode = Con THEN x.mode := Based; x.offset := z.offset
ELSE Load(z, -1); MakeReg(z, -1); x.mode := Indexed; x.offset := z.reg
END;
x.typ := y.typ; Assign(y, x)
END SYSget;
PROCEDURE SYSput* (VAR x, z, y: OPL.Item);
BEGIN
Load(x, -1); MakeReg(x, -1);
IF z.mode = Con THEN x.mode := Based; x.offset := z.offset
ELSE Load(z, -1); MakeReg(z, -1); x.mode := Indexed; x.offset := z.reg
END;
x.typ := y.typ; Assign(x, y)
END SYSput;
PROCEDURE SYSgetreg* (VAR x, y: OPL.Item);
VAR t, form: LONGINT; reg: BOOLEAN; z: OPL.Item;
BEGIN
ASSERT(y.mode = Con);
IF y.offset < 32 THEN
y.mode := Reg; y.reg := y.offset; y.typ := x.typ; Assign(x, y)
ELSIF y.offset < 66 THEN
IF x.typ^.form IN {LInt, Set} THEN
reg := x.mode = Reg;
IF reg THEN t := x.reg ELSE t := OPL.GetTempR() END;
IF y.offset = 64 THEN OPL.Put(iMFCR+t*fRT)
ELSIF y.offset = 65 THEN OPL.Put(iMFMSR+t*fRT)
ELSE OPL.Put(iMFSPR+t*fRT+(y.offset-32)*fSPR)
END;
IF ~reg THEN y.mode := Reg; y.reg := t; y.typ := x.typ; Assign(x, y) END
ELSE OPM.err(250)
END
ELSE (* y.offset = 66 *)
reg := x.mode = FReg;
IF reg THEN t := x.reg ELSE t := OPL.GetTempF() END;
OPL.Put(iMFFS+t*fFRT);
IF ~reg THEN form := x.typ^.form;
IF form = LReal THEN
y.mode := FReg; y.reg := t; y.typ := x.typ; Assign(x, y)
ELSIF form IN {LInt, Set} THEN
IF scratch < 0 THEN scratch := OPL.dsize; INC(OPL.dsize, 8) END;
z.mode := Based; z.reg := SB; z.offset := scratch; z.typ := OPT.lrltyp; z.dreg := -1; Store(z, y);
z.mode := Based; z.offset := scratch+4; z.reg := SB; z.typ := x.typ; Assign(x, z)
END
END
END
END SYSgetreg;
PROCEDURE SYSputreg* (VAR x, y: OPL.Item);
VAR z: OPL.Item;
BEGIN
ASSERT(x.mode = Con);
IF x.offset < 32 THEN
x.mode := Reg; x.reg := x.offset; x.typ := y.typ; Assign(x, y)
ELSIF x.offset < 66 THEN
IF y.typ^.form IN {LInt, Set} THEN
Load(y, -1);
IF x.offset = 64 THEN OPL.Put(iMTCRF+y.reg*fRS+255*fFXM)
ELSIF x.offset = 65 THEN OPL.Put(iMTMSR+y.reg*fRS)
ELSE OPL.Put(iMTSPR+y.reg*fRS+(x.offset-32)*fSPR)
END;
OPL.FreeTempR(y.reg)
ELSE OPM.err(250)
END
ELSE (* x.offset = 66 *)
IF y.typ^.form IN {LInt, Set} THEN
IF y.mode = Reg THEN
IF scratch < 0 THEN scratch := OPL.dsize; INC(OPL.dsize, 8) END;
z.mode := Based; z.reg := SB; z.offset := scratch+4; z.typ := y.typ; z.dreg := -1; Assign(z, y);
y.mode := Based; y.reg := SB; y.offset := scratch
ELSE Base(y, -1); DEC(y.offset, 4)
END;
y.typ := OPT.lrltyp
END;
Load(y, -1);
OPL.Put(iMTFSF+255*fFLM+y.reg*fFRB); OPL.FreeTempF(y.reg)
END
END SYSputreg;
PROCEDURE SYSmove* (VAR x, y, z: OPL.Item);
BEGIN
Load(x, -1); Load(y, -1); x.mode := Based; x.offset := 0; y.mode := Based; y.offset := 0; Move(x, y, z, FALSE)
END SYSmove;
PROCEDURE NewSys* (VAR x, y: OPL.Item; rt: LONGINT);
VAR saved: OPL.SaveDesc;
BEGIN
x.mode := XProc; x.reg := 0; x.typ := OPT.notyp; x.dreg := -1; OPL.SaveRegisters(x, saved, sSize);
x.mode := Reg; x.reg := 3; x.typ := OPT.linttyp; Assign(x, y);
x.mode := XProc; x.mnolev := -SYSTEM.VAL(SHORTINT, SYSMTag);
x.offset := ORD(NewSysETag); x.adr := NewSysEntry;
OPL.Put(iL+SB*fRT+SB*fRA+(OPL.linkTable MOD LowWord)); OPL.PutXCall(x);
NewSysEntry := x.adr; OPL.Put(iL+SB*fRT+SP*fRA+20);
x.mode := Reg; x.reg := 3; x.typ := OPT.linttyp; OPL.RestoreRegisters(x, saved, rt)
END NewSys;
PROCEDURE NewArr* (VAR x, nofel: OPL.Item; nofdim: LONGINT; typ: OPT.Struct; rt: LONGINT);
VAR y: OPL.Item; saved: OPL.SaveDesc;
BEGIN
OPL.FreePar;
IF (typ^.form # Pointer) & (typ^.tdadr > -3) THEN (* simple type *)
y.mode := Con; y.offset := typ^.size; y.typ := OPT.linttyp; y.dreg := -1; OPL.LockParR(3); MulOrShift(nofel, y, 3);
IF nofel.mode = Con THEN INC(nofel.offset, (nofdim DIV 2)*8+16)
ELSE y.mode := Con; y.typ := OPT.linttyp; y.offset := (nofdim DIV 2)*8+16;
Load(nofel, -1); IntAddImm(nofel, y, 3)
END;
OPL.FreePar; NewSys(x, nofel, rt)
ELSE
x.mode := XProc; x.reg := 0; x.typ := OPT.notyp; x.dreg := -1;
OPL.SaveRegisters(x, saved, sSize);
x.mode := Reg; x.typ := OPT.linttyp;
x.reg := 4; OPL.LockParR(4); Assign(x, nofel);
x.reg := 5; OPL.LockParR(5); y.mode := Con; y.offset := nofdim; y.typ := OPT.linttyp; Assign(x, y);
x.reg := 3; OPL.LockParR(3);
IF typ^.form = Pointer THEN y.mode := Con; y.offset := 0; y.typ := OPT.linttyp
ELSE y.mode := Var; y.mnolev := -typ^.mno; y.offset := typ^.tdadr; y.typ := OPT.linttyp
END;
Assign(x, y); OPL.FreePar;
x.mode := XProc; x.mnolev := -SYSTEM.VAL(SHORTINT, SYSMTag);
x.offset := ORD(NewArrETag); x.adr := NewArrEntry;
OPL.Put(iL+SB*fRT+SB*fRA+(OPL.linkTable MOD LowWord)); OPL.PutXCall(x);
NewArrEntry := x.adr; OPL.Put(iL+SB*fRT+SP*fRA+20);
x.mode := Reg; x.reg := 3; x.typ := OPT.linttyp; OPL.RestoreRegisters(x, saved, rt)
END
END NewArr;
PROCEDURE NewRec* (VAR x: OPL.Item; typ: OPT.Struct; rt: LONGINT);
VAR y: OPL.Item; saved: OPL.SaveDesc; len: LONGINT; btyp: OPT.Struct;
BEGIN
IF typ^.tdadr > -3 THEN (* no type descriptor allocated *)
IF typ^.comp = Array THEN len := typ^.n; btyp := typ^.BaseTyp;
WHILE btyp^.comp = Array DO len := len*btyp^.n; btyp := btyp^.BaseTyp END;
y.mode := Con; y.typ := OPT.linttyp;
IF (btyp^.comp = Record) OR (btyp^.form = Pointer) THEN y.offset := len; NewArr(x, y, 1, btyp, rt)
ELSE y.offset := typ^.size; NewSys(x, y, rt)
END
ELSE
y.mode := Con; y.offset := typ^.size; y.typ := OPT.linttyp; NewSys(x, y, rt)
END
ELSE
x.mode := XProc; x.reg := 0; x.typ := OPT.notyp; x.dreg := -1; OPL.SaveRegisters(x, saved, sSize);
y.mode := Var; y.mnolev := -typ^.mno; y.offset := typ^.tdadr; y.typ := OPT.linttyp;
x.mode := Reg; x.reg := 3; x.typ := OPT.linttyp; Assign(x, y);
x.mode := XProc; x.mnolev := -SYSTEM.VAL(SHORTINT, SYSMTag);
x.offset := ORD(NewRecETag); x.adr := NewRecEntry;
OPL.Put(iL+SB*fRT+SB*fRA+(OPL.linkTable MOD LowWord)); OPL.PutXCall(x);
NewRecEntry := x.adr; OPL.Put(iL+SB*fRT+SP*fRA+20);
x.mode := Reg; x.reg := 3; x.typ := OPT.linttyp; OPL.RestoreRegisters(x, saved, rt)
END
END NewRec;
PROCEDURE SetDim* (VAR y, len: OPL.Item; typ: OPT.Struct);
VAR z: OPL.Item;
BEGIN
z := y; INC(z.offset, typ^.offset); OPL.UnholdTempR(len.reg); Assign(z, len)
END SetDim;
PROCEDURE ArrayLen (VAR x: OPL.Item; rt: LONGINT);
VAR typ: OPT.Struct;
BEGIN
typ := x.typ;
IF typ^.comp = Array THEN
x.mode := Con; x.offset := typ^.n
ELSE ASSERT(typ^.comp = DynArr);
IF x.dmode = Reg THEN x.mode := Reg; x.reg := x.dreg + typ^.offset DIV 4
ELSE ASSERT(x.dmode = Based);
x.mode := Based; x.reg := x.dreg; x.offset := x.adr + typ^.offset
END
END;
x.typ := OPT.linttyp
END ArrayLen;
PROCEDURE PPCcopy (VAR x, y: OPL.Item); (* copy y to x, PowerPC sequence *)
VAR z: OPL.Item; t0, t1, src, dest, cond, h: LONGINT; loop, end0, end1, end: OPL.Label;
BEGIN
Base(x, -1); ShortBase(x, -1);
Base(y, -1); ShortBase(y, -1); OPL.UnholdTempR(y.dreg);
z := x; ArrayLen(z, -1);
t0 := OPL.GetTempR(); t1 := OPL.GetTempR(); cond := OPL.GetTempCRF();
Load(z, -1); OPL.FreeTempR(z.reg); OPL.Put(iMTSPR+z.reg*fRS+spCTR*fSPR);
dest := x.reg; src := y.reg;
IF ~(dest IN OPL.TempRegs) THEN
h := OPL.GetTempR(); OPL.Put(iCAL+h*fRT+dest*fRA+(x.offset MOD LowWord)); x.offset := 0; dest := h
END;
IF ~(src IN OPL.TempRegs) THEN
h := OPL.GetTempR(); OPL.Put(iCAL+h*fRT+src*fRA+(y.offset MOD LowWord)); y.offset := 0; src := h
END;
end0 := 0; end1 := 0; end := 0; loop := 0;
IF y.offset # 0 THEN OPL.Put(iLBZU+t0*fRT+src*fRA+(y.offset MOD LowWord)) ELSE OPL.Put(iLBZ+t0*fRT+src*fRA) END;
OPL.Put(iCAL);
PutBranchInstr(iBDZ, end0);
OPL.Put(iCMPI+cond*fBF+t0*fRA+0);
PutBranchInstr(iBT+(cond*4+bEQ)*fBI, end0);
OPL.Put(iLBZU+t1*fRT+src*fRA+1);
IF x.offset # 0 THEN OPL.Put(iSTBU+t0*fRS+dest*fRA+(x.offset MOD LowWord)) ELSE OPL.Put(iSTB+t0*fRS+dest*fRA) END;
PutBranchInstr(iBDZ, end1);
OPL.Put(iCMPI+cond*fBF+t1*fRA+0);
PutBranchInstr(iBT+(cond*4+bEQ)*fBI, end1);
SetLabel(loop);
OPL.Put(iLBZU+t0*fRT+src*fRA+1);
OPL.Put(iSTBU+t1*fRS+dest*fRA+1);
PutBranchInstr(iBDZ, end1);
OPL.Put(iCMPI+cond*fBF+t0*fRA+0);
PutBranchInstr(iBT+(cond*4+bEQ)*fBI, end1);
OPL.Put(iLBZU+t1*fRT+src*fRA+1);
OPL.Put(iSTBU+t0*fRS+dest*fRA+1);
PutBranchInstr(iBDZ, end1);
OPL.Put(iCMPI+cond*fBF+t0*fRA+0);
PutBranchInstr(iBF+(cond*4+bEQ)*fBI, loop);
SetLabel(end1);
OPL.Put(iSTB+0*fRS+dest*fRA+1);
PutBranch(end);
SetLabel(end0);
OPL.Put(iSTB+0*fRS+dest*fRA+(x.offset MOD LowWord));
SetLabel(end);
OPL.FreeTempR(t0); OPL.FreeTempR(t1); OPL.FreeTempR(src); OPL.FreeTempR(dest); OPL.FreeTempCRBs({cond*4..cond*4+3})
END PPCcopy;
PROCEDURE POWERcopy (VAR x, y: OPL.Item); (* copy y to x, POWER sequence *)
VAR len, a, b: OPL.Item;
first, cnt, src, dest, lreg: LONGINT; used: SET;
styp, dtyp: OPT.Struct;
restOnly, noLoop, noLenChk: BOOLEAN;
end, rest, loop: OPL.Label;
BEGIN
styp := y.typ; dtyp := x.typ;
IF x.mode = Based THEN used := {x.reg} ELSE used := {x.reg, x.offset} END;
first := 3;
WHILE first IN used DO INC(first) END;
LoadAddr(y, first);
IF y.reg = first THEN INCL(used, first)
ELSIF y.reg IN OPL.TempRegs THEN MoveReg(first, y.reg); OPL.FreeTempR(y.reg); y.reg := first; INCL(used, first)
END;
IF dtyp^.comp = Array THEN
IF x.mode = Based THEN EXCL(used, x.reg) ELSE used := used - {x.reg, x.offset} END
END;
first := 3;
WHILE first IN used DO INC(first) END;
len := x; lreg := -1;
LoadAddr(x, first);
IF x.mode = Based THEN EXCL(used, x.reg) ELSE used := used - {x.reg, x.offset} END;
IF x.reg = first THEN INCL(used, first)
ELSIF x.reg IN OPL.TempRegs THEN MoveReg(first, x.reg); OPL.FreeTempR(x.reg); x.reg := first; INCL(used, first)
END;
IF dtyp^.comp = DynArr THEN first := 3;
WHILE first IN used DO INC(first) END;
lreg := first; INCL(used, first)
END;
used := used * OPL.TempRegs;
IF used = {} THEN first := 3
ELSE first := 12;
WHILE ~(first IN used) DO DEC(first) END;
INC(first)
END;
noLenChk := FALSE; cnt := (12-first)*4;
IF styp.comp = Array THEN
IF dtyp.comp = Array THEN noLenChk := styp.n <= dtyp.n;
IF noLenChk THEN INC(cnt, 4) END;
restOnly := (styp.n <= cnt) OR (dtyp.n <= cnt);
noLoop := (styp.n <= 2*cnt) OR (dtyp.n <= 2*cnt)
ELSE restOnly := styp.n <= cnt; noLoop := styp.n <= 2*cnt
END
ELSIF dtyp.comp = Array THEN restOnly := dtyp.n <= cnt; noLoop := dtyp.n <= 2*cnt
END;
end := 0; rest := 0;
IF ~noLenChk OR restOnly THEN
IF lreg = -1 THEN first := 3;
WHILE first IN used DO INC(first) END;
lreg := first;
IF ~noLenChk THEN INCL(used, lreg) END;
used := used * OPL.TempRegs;
IF used = {} THEN first := 3
ELSE first := 12;
WHILE ~(first IN used) DO DEC(first) END;
INC(first)
END
END;
ArrayLen(len, lreg); Load(len, lreg);
IF ~restOnly THEN INCL(used, lreg);
IF (len.reg # lreg) THEN MoveReg(lreg, len.reg); OPL.FreeTempR(len.reg); len.reg := lreg END
END
END;
ASSERT(first+(cnt DIV 4) <= 13);
src := y.reg; dest := x.reg;
end := 0; rest := 0;
IF ~restOnly THEN
OPL.Put(iLIL+first*fRT+cnt); OPL.Put(iMTXER+first*fRS);
IF noLoop THEN OPL.Put(iLIL+0*fRT+0)
ELSE
OPL.Put(iLIL+0*fRT+((-cnt) MOD LowWord));
loop := 0; SetLabel(loop);
OPL.Put(iADDIC+0*fRT+0*fRA+cnt)
END;
IF ~noLenChk THEN
OPL.Put(iADDICR+len.reg*fRT+len.reg*fRA+((-cnt) MOD LowWord));
PutBranchInstr(iBF+bGT*fBI, rest)
END;
OPL.Put(iLSCBX+first*fRT+src*fRA+0*fRB+fREC);
OPL.Put(iSTSX+first*fRS+dest*fRA+0*fRB);
IF noLoop THEN PutBranchInstr(iBT+bEQ*fBI, end); OPL.Put(iADDIC+0*fRT+0*fRA+cnt)
ELSE PutBranchInstr(iBF+bEQ*fBI, loop);
IF ~noLenChk THEN PutBranchInstr(iBA, end) END
END
END;
SetLabel(rest);
IF ~noLenChk OR restOnly THEN
IF ~noLenChk & ~restOnly THEN OPL.Put(iADDIC+len.reg*fRT+len.reg*fRA+cnt) END;
OPL.Put(iMTXER+len.reg*fRS);
IF restOnly THEN OPL.Put(iLIL+0*fRT+0) END;
OPL.Put(iLSCBX+first*fRT+src*fRA+0*fRB+fREC);
OPL.Put(iSTSX+first*fRS+dest*fRA+0*fRB);
IF ~noLenChk THEN
PutBranchInstr(iBT+bEQ*fBI, end);
IF ~restOnly THEN OPL.Put(iLIL+0*fRT+0) END;
b.mode := Reg; b.reg := 0; b.typ := OPT.chartyp;
a.reg := dest; a.typ := OPT.chartyp;
IF dtyp^.comp = Array THEN a.mode := Based; a.offset := dtyp^.n-1
ELSE
OPL.Put(iADDI+len.reg*fRT+len.reg*fRA+((-1) MOD LowWord));
OPL.Put(iADD+len.reg*fRT+len.reg*fRA+0*fRB);
a.mode := Indexed; a.offset := len.reg
END;
Store(a, b)
END
END;
SetLabel(end);
OPL.FreeTempR(src); OPL.FreeTempR(dest); OPL.FreeTempR(len.reg)
END POWERcopy;
PROCEDURE Copy* (VAR x, y: OPL.Item); (* copy y to x *)
VAR len: OPL.Item;
BEGIN
IF (y.typ^.form = String) & (x.typ^.comp = Array) THEN
len.mode := Con; len.offset := y.adr; len.typ := OPT.linttyp; Move(x, y, len, TRUE)
ELSIF TRUE (*powerpc IN options*) THEN PPCcopy(x, y)
ELSE POWERcopy(x, y)
END
END Copy;
PROCEDURE With* (VAR x: OPL.Item);
BEGIN
IF x.mode IN {Reg, Based, Indexed} THEN OPL.FreeTempR(x.reg) END;
IF x.mode = Indexed THEN OPL.FreeTempR(x.offset) END
END With;
PROCEDURE Msk* (VAR x, y: OPL.Item; rt: LONGINT);
VAR s, mb: LONGINT;
BEGIN y.offset := -1-y.offset;
ASSERT((y.mode = Con) & (SYSTEM.VAL(SET, y.offset)*SYSTEM.VAL(SET, y.offset+1) = {}));
Load(x, -1); mb := CNTLZ(y.offset); IF mb < 24 THEN MakeReg(x, -1) END;
s := x.reg; OPL.FreeTempR(s); rt := CheckR(rt); OPL.Put(iRLINM+rt*fRA+s*fRS+mb*fMB+31*fME);
x.mode := Reg; x.reg := rt
END Msk;
(* MskAsh and AshMsk, experimental
PROCEDURE Compare* (VAR x, y: OPL.Item; subcl: INTEGER);
VAR f, tidx, s1, s2, t1, t2, b, bitNo: LONGINT; pol: BOOLEAN; tlab, lstlab, lastlab, endlab: OPL.Label; z: OPL.Item;
BEGIN
CASE x.typ^.form OF
Real, LReal:
Load(x, -1); Load(y, -1); s1 := x.reg; s2 := y.reg; OPL.FreeTempF(s1); OPL.FreeTempF(s2);
f := OPL.GetTempCRF(); OPL.Put(iFCMPU+f*fBF+s1*fFRA+s2*fFRB)
| Byte, Char, SInt, Int, LInt, Set, Pointer, ProcTyp:
IF x.typ^.form = ProcTyp THEN x.typ := OPT.linttyp; y.typ := OPT.linttyp END;
IF x.mode = Con THEN subcl := switch[subcl-eql]; f := IntCmpImm(y, x)
ELSIF y.mode = Con THEN f := IntCmpImm(x, y)
ELSE f := IntCmp(x, y)
END
| Bool:
IF (x.mode = Cond) OR (y.mode = Cond) THEN
IF x.mode # Cond THEN Load(x, -1); RegToCond(x) END;
IF y.mode # Cond THEN Load(y, -1); RegToCond(y) END;
pol := subcl = eql; s1 := x.reg; s2 := y.reg;
IF s1 < 0 THEN s1 := -1-s1; pol := ~pol END;
IF s2 < 0 THEN s2 := -1-s2; pol := ~pol END;
OPL.FreeTempCRBs({s1, s2}); bitNo := OPL.GetTempCRB();
IF pol THEN f := iCREQV ELSE f := iCRXOR END;
OPL.Put(f+bitNo*fBT+s1*fBA+s2*fBB);
x.mode := Cond; x.reg := bitNo; RETURN
ELSE
f := IntCmp(x, y)
END
| String, Comp: (*
LoadAddr (x, -1); LoadAddr (y, -1);
s1 := OPL.GetTempR (); s2 := OPL.GetTempR ();
OPL.Put (iCAL+s1*fRT+x.reg*fRA+65535);
OPL.Put (iCAL+s2*fRT+y.reg*fRA+65535);
tidx := OPL.GetTempR (); t1 := OPL.GetTempR (); t2 := OPL.GetTempR ();
f := OPL.GetTempCRF ();
lstlab := 0; lastlab := 0;
OPL.Put (iCAL+tidx*fRT+1);
SetLabel (lstlab);
OPL.Put (iLBZUX+t1*fRT+s1*fRA+tidx*fRB);
OPL.Put (iLBZUX+t2*fRT+s2*fRA+tidx*fRB);
OPL.Put (iCMP+f*fBF+t1*fRA+t2*fRB);
PutBranchInstr (iBF+(f*4+bEQ)*fBI, lastlab);
OPL.Put (iCMPI+f*fBF+t1*fRA+0);
PutBranchInstr (iBF+(f*4+bEQ)*fBI, lstlab);
OPL.Put (iCMP+f*fBF+t1*fRA+t2*fRB);
SetLabel (lastlab);
OPL.FreeTempR (s1); OPL.FreeTempR (s2);
OPL.FreeTempR (x.reg); OPL.FreeTempR (y.reg);
OPL.FreeTempR (tidx); OPL.FreeTempR (t1); OPL.FreeTempR (t2)
END;
bitNo := CRbit[subcl-eql]; b := bitNo; IF b < 0 THEN b := -1-b END;
INC(b, f*4); OPL.FreeTempCRBs({f*4..f*4+3}-{b}); IF bitNo < 0 THEN b := -1-b END;
x.mode := Cond; x.reg := b
END Compare;
PROCEDURE Len* (VAR x, y: OPL.Item; rt: LONGINT);
BEGIN
ASSERT(x.mode = Based); OPL.FreeTempR(x.reg);
IF x.dmode = Reg THEN
x.mode := Reg; x.reg := x.dreg+y.offset+1
ELSE
x.mode := x.dmode; x.reg := x.dreg; x.offset := x.adr+y.offset*4+4
END;
IF x.dreg # -1 THEN OPL.UnholdTempR(x.dreg); OPL.FreeTempR(x.dreg); x.dreg := -1 END
END Len;
PROCEDURE SYSbit* (VAR x, y: OPL.Item);
VAR z: OPL.Item;
BEGIN
Load(x, -1); MakeReg(x, -1); z := x; z.mode := Based; z.offset := 0; z.typ := OPT.settyp;
x.mode := y.mode; x.reg := y.reg; x.offset := y.offset; x.typ := y.typ; x.dreg := y.dreg; In(x, z)
END SYSbit;
PROCEDURE Trap* (type: INTEGER);
BEGIN OPL.SetTrap(type); OPL.Put(iT+tALWAYS*fTO)
END Trap;
PROCEDURE EnterLoop*;
BEGIN DEC(LoopLevel); LoopStart[LoopLevel] := 0; LoopEnd[LoopLevel] := 0; SetLabel(LoopStart[LoopLevel])
END EnterLoop;
PROCEDURE ExitLoop*;
BEGIN PutBranch(LoopEnd[LoopLevel])
END ExitLoop;
PROCEDURE EndLoop*;
BEGIN PutBranch(LoopStart[LoopLevel]); SetLabel(LoopEnd[LoopLevel]); INC(LoopLevel)
END EndLoop;
PROCEDURE Case* (VAR x: OPL.Item; low, high: LONGINT; VAR table: LONGINT);
VAR y: OPL.Item; c, t1, t2: LONGINT;
BEGIN
Load(x, -1); MakeReg(x, -1); x.typ := OPT.linttyp; y.dreg := -1;
IF low # 0 THEN
y.mode := Con; y.offset := low; y.typ := OPT.linttyp; Minus(x, y, -1); DEC(high, low)
END;
t1 := x.reg; ASSERT(high <= 32767);
c := OPL.GetTempCRF(); OPL.Put(iCMPLI+c*fBF+t1*fRA+high); c := c*4; OPL.FreeTempCRBs({c..c+3}-{c+bGT});
y.mode := Cond; y.reg := c+bGT; y.Tjmp := 0; y.Fjmp := 0; y.typ := OPT.booltyp; PutCondBranch(y, TRUE);
OPL.FreeTempR(t1); t2 := OPL.GetTempR(); OPL.FreeTempR(t2); OPL.Put(iRLINM+t2*fRA+t1*fRS+2*fSH+29*fME);
OPL.AllocCaseTable(high, table);
t1 := OPL.GetTempR(); OPL.FreeTempR(t1); OPL.Put(iCAL+t1*fRT+SB*fRA+(table MOD 10000H));
y.mode := Indexed; y.reg := t1; y.offset := t2; y.typ := OPT.linttyp; Load(y, -1);
ASSERT(y.mode = Reg);
t1 := y.reg; OPL.FreeTempR(t1); OPL.Put(iMTSPR+spCTR*fSPR+t1*fRS);
OPL.SetCaseBranch(table); OPL.Put(iBCC+cALWAYS*fBO);
SetLabel(y.Tjmp); OPL.FixCase(0, high, table)
END Case;
PROCEDURE Call* (VAR x: OPL.Item; outparsize: LONGINT);
VAR sl, t, offset: LONGINT; y, z: OPL.Item;
BEGIN
y.dreg := -1; z.dreg := -1;
IF outparsize > aopSize+32 THEN aopSize := outparsize-32 END;
IF (x.mode = LProc) OR (x.mode = XProc) & (x.mnolev = 0) THEN
IF x.mnolev > 0 THEN
sl := FindFP(OPL.level, x.mnolev, SLpar);
IF sl # SLpar THEN sl := CheckVFP(sl); OPL.Put(iCAL+SLpar*fRT+sl*fRA) END
END;
OPL.PutLCall(x)
ELSIF x.mode = XProc THEN
y.mode := Based; y.reg := SB; y.offset := -(x.mnolev*4)+OPL.linkTable; y.typ := OPT.linttyp;
z.mode := Reg; z.reg := SB; z.typ := OPT.linttyp; Assign(z, y);
OPL.PutXCall(x);
OPL.Put(iL+SB*fRT+SP*fRA+20);
ELSE (* x.mode IN {Var, VarPar, Based, Reg} *)
IF x.mode # Reg THEN
Base(*OrInx*)(x, -1); ShortBase(x, -1); t := x.reg; offset := x.offset; OPL.FreeTempR(t);
OPL.Put(iL+t*fRA+(offset MOD LowWord));
OPL.Put(iMTSPR+spCTR*fSPR); OPL.Put(iL+SB*fRT+t*fRA+((offset+4) MOD LowWord))
ELSE
t := x.reg; OPL.Put(iMTSPR+spCTR*fSPR+t*fRS); MoveReg(SB, t+1)
END;
OPL.Put(iBCC+cALWAYS*fBO+fLK); OPL.Put(iL+SB*fRT+SP*fRA+20)
END
END Call;
PROCEDURE GetMethod* (VAR x: OPL.Item; typ: OPT.Struct; deref, super: BOOLEAN);
VAR tag: OPL.Item;
BEGIN
IF super THEN
IF typ^.form = Pointer THEN typ := typ^.BaseTyp END;
typ := typ^.BaseTyp;
tag.mode := Var; tag.mnolev := -typ^.mno; tag.offset := typ^.tdadr; tag.typ := OPT.linttyp; tag.dreg := -1;
Load(tag, -1);
x.mode := Based; x.reg := tag.reg; x.offset := -76-x.offset*8
ELSE
IF deref THEN
tag.mode := Based; tag.reg := 3; tag.offset := -4; tag.typ := OPT.linttyp; tag.dreg := -1;
Load(tag, -1);
x.mode := Based; x.reg := tag.reg; x.offset := -76-x.offset*8
ELSE
x.mode := Based; x.reg := 4; x.offset := -76-x.offset*8
END
END
END GetMethod;
PROCEDURE SaveRegisters* (VAR x: OPL.Item; VAR saved: OPL.SaveDesc);
BEGIN OPL.SaveRegisters(x, saved, sSize)
END SaveRegisters;
PROCEDURE RestoreRegisters* (VAR res: OPL.Item; VAR saved: OPL.SaveDesc; rt: LONGINT);
BEGIN OPL.RestoreRegisters(res, saved, rt)
END RestoreRegisters;
PROCEDURE DynArrCopy (p: OPT.Object; leaf, saveCR: BOOLEAN);
VAR t0, t1, t2, t3, t4, ralloc, rt: LONGINT; x, y, z, h, hd: OPL.Item; typ: OPT.Struct; loop: OPL.Label;
BEGIN
(* get source into y, dest into x *)
typ := p^.typ; ralloc := p^.adr; y.typ := OPT.linttyp; y.dreg := -1;
IF ralloc < 0 THEN ralloc := -1-ralloc; y.mode := SHORT(SHORT(ralloc DIV 32)); y.reg := ralloc MOD 32
ELSE y.mode := Based; y.reg := FP; y.offset := (*ralloc*) p^.linkadr
END;
y.dmode := y.mode; y.dreg := SHORT(SHORT(y.reg)); y.adr := y.offset;
ralloc := p^.linkadr; x.typ := OPT.linttyp;
IF ralloc < 0 THEN ralloc := -1-ralloc; x.mode := SHORT(SHORT(ralloc DIV 32)); rt := ralloc MOD 32; x.reg := rt
ELSE x.mode := Based; x.reg := FP; x.offset := ralloc; rt := -1
END;
x.dmode := x.mode; x.dreg := SHORT(SHORT(x.reg)); x.adr := x.offset;
(* move len part of descriptor *)
hd := x; h.typ := OPT.linttyp; h.dreg := -1;
IF y.dmode = Reg THEN
t0 := typ^.n; h.mode := Reg; h.reg := y.dreg+1;
WHILE t0 >= 0 DO
IF hd.mode = Reg THEN INC(hd.reg) ELSE INC(hd.offset, 4) END;
Assign(hd, h); INC(h.reg); DEC(t0)
END
END;
(* compute type size into z *)
Load(y, -1); y.mode := Based; y.offset := 0; y.dmode := x.dmode; y.dreg := x.dreg; y.adr := x.adr; z := y;
TypeSize(z, typ, -1); Load(z, -1); MakeReg(z, -1); t0 := z.reg;
(* align to 8 and allocate the space *)
t1 := OPL.GetTempR(); OPL.Put(iL+t1*fRT+SP*fRA); (* t1 = dynamic link *)
t2 := OPL.GetTempR(); OPL.Put(iAI+t2*fRT+t0*fRA+7);
OPL.FreeTempR(t0); t0 := OPL.GetTempR(); OPL.Put(iRLINM+t2*fRS+t0*fRA+28*fME); OPL.FreeTempR(t2);
(*z.reg := t0; *)OPL.Put(iSF+SP*fRT+t0*fRA+SP*fRB); OPL.Put(iST+t1*fRS+SP*fRA); OPL.FreeTempR(t1);
IF ~leaf THEN
OPL.Put(iST+SB*fRS+SP*fRA+20); (*OPL.Put(iST+t4*fRS+SP*fRA+8); OPL.FreeTempR(t4)*)
END;
(* this is the assignment of the new pointer *)
rt := CheckR(rt); OPL.Put(iCAL+rt*fRT+SP*fRA+(FPlink MOD LowWord)); FPlink := SHORT(1-OPL.pc);
h.mode := Reg; h.reg := rt; h.typ := OPT.linttyp; Assign(x, h);
(* this is the actual move step *)
OPL.FreeTempR(t0); t1 := OPL.GetTempR(); OPL.Put(iRLINM+t0*fRS+t1*fRA+29*fSH+3*fMB+31*fME);
OPL.Put(iMTSPR+t1*fRS+spCTR*fSPR); OPL.FreeTempR(t1);
DEC(y.offset, 4); LoadAddr(y, -1); t1 := y.reg;
t0 := OPL.GetTempR(); OPL.Put(iCAL+t0*fRT+SP*fRA+(FPlink4 MOD LowWord)); FPlink4 := SHORT(1-OPL.pc);
(*t2 := OPL.GetTempRegs(2, {}); t3 := t2+1;*) t2 := OPL.GetTempR(); t3 := OPL.GetTempR();
loop := 0; SetLabel(loop);
OPL.Put(iLU+t2*fRT+t1*fRA+4); OPL.Put(iLU+t3*fRT+t1*fRA+4);
OPL.Put(iSTU+t2*fRS+t0*fRA+4); OPL.Put(iSTU+t3*fRS+t0*fRA+4);
PutBranchInstr(iBCNTNZ, loop);
(*OPL.FreeTempRegs(t2, 2); *) OPL.FreeTempR(t2); OPL.FreeTempR(t3); OPL.FreeTempR(t0); OPL.FreeTempR(t1)
END DynArrCopy;
PROCEDURE InitPtrs* (proc: OPT.Object);
CONST MaxPtrs = 16;
VAR
reg, ptr: LONGINT; nofptrs: INTEGER;
ptrTab: ARRAY MaxPtrs+1 OF LONGINT;
obj, lastobj: OPT.Object;
size, x: OPL.Item;
loop: OPL.Label;
BEGIN
reg := -1; obj := proc^.scope^.scope; (* local variables *)
WHILE obj # NIL DO (* find pointer registers *)
IF (obj^.linkadr < -1) & (obj^.typ^.form = Pointer) THEN
reg := (-1-obj^.linkadr) MOD 32; OPL.Put(iCAL+reg*fRT)
END;
obj := obj^.link
END;
nofptrs := 0; obj := proc^.scope^.scope;
WHILE (obj # NIL) & (nofptrs <= MaxPtrs) DO (* find pointers in memory *)
IF obj^.linkadr >= 0 THEN OPL.FindPtrs(obj^.typ, obj^.linkadr, ptrTab, nofptrs); lastobj := obj END;
obj := obj^.link
END;
IF nofptrs > MaxPtrs THEN (* initialize from the first pointer to the end of the frame *)
obj := lastobj;
WHILE obj # NIL DO
IF obj^.linkadr >= 0 THEN lastobj := obj END;
obj := obj^.link
END;
size.mode := Con; size.typ := OPT.linttyp; size.offset := (lastobj^.linkadr + lastobj^.typ^.size - ptrTab[0]) DIV 4;
Load(size, -1); OPL.Put(iMTSPR+spCTR*fSPR+size.reg*fRS); OPL.FreeTempR(size.reg);
IF reg < 0 THEN reg := 0; OPL.Put(iCAL) END;
IF ptrTab[0] = 4 THEN (* address to be loaded would become 0(FP), therefore copy *)
ptr := OPL.GetTempR(); OPL.Put(iCAL+ptr*fRT+FP*fRA)
ELSE
x.mode := Based; x.reg := FP; x.offset := ptrTab[0]-4; x.typ := OPT.linttyp;
LoadAddr(x, -1); ptr := x.reg
END;
SetLabel(loop); OPL.Put(iSTU+reg*fRS+ptr*fRA+4); PutBranchInstr(iBCNTNZ, loop);
OPL.FreeTempR(ptr)
ELSIF nofptrs > 0 THEN
IF reg < 0 THEN reg := 0; OPL.Put(iCAL) END;
size.typ := OPT.linttyp; size.mode := Reg; size.reg := reg;
x.typ := OPT.linttyp; x.mode := Based;
WHILE nofptrs > 0 DO DEC(nofptrs);
x.reg := FP; x.offset := ptrTab[nofptrs]; Store(x, size)
END
END
END InitPtrs;
PROCEDURE Enter* (n: OPT.Object);
VAR l: OPL.Label; x, y: OPL.Item; ralloc, falloc, calloc, fsize: LONGINT; parR, parF: SET;
p: OPT.Object; typ: OPT.Struct; form, comp, nrReg: LONGINT; rdest, leaf: BOOLEAN;
BEGIN
x.dreg := -1; y.dreg := -1;
IF n # NIL THEN
IF n^.mode = LProc THEN
l := SHORT(n^.adr); IF l = -1 THEN l := 0 END;
SetLabel(l); n^.adr := l
ELSE
ralloc := n^.adr MOD LowWord;
IF OPL.entry[ralloc] = -1 THEN OPL.entry[ralloc] := 0 END;
SetLabel(OPL.entry[ralloc])
END;
FP := 31;
fsize := n^.conval^.intval2; calloc := n^.conval^.intval; ralloc := (calloc DIV 1024) MOD 32;
falloc := (calloc DIV 32) MOD 32; calloc := calloc MOD 32;
parR := n^.conval^.setval; parF := SYSTEM.ROT(parR, -16)*{1..13}; parR := SYSTEM.LSH(parR, -1)*{3..10};
leaf := n^.leaf & (falloc = 31); n^.leaf := leaf;
IF n^.mnolev > 0 THEN INCL(parR, SLpar) END
ELSE
ralloc := 30; falloc := 31; calloc := 19; fsize := 8; parR := {}; parF := {}; FP := 31; leaf := FALSE;
IF OPL.entry[0] = -1 THEN OPL.entry[0] := 0 END;
SetLabel(OPL.entry[0])
END;
OPL.LockTempR(parR); OPL.LockTempF(parF);
OPL.GenProcEntry(fsize, ralloc, falloc, calloc, FP, leaf, (n # NIL) & (n^.mnolev > 0));
IF n # NIL THEN p := n^.link;
WHILE p # NIL DO
IF p^.adr < 0 THEN
typ := p^.typ; form := typ^.form;
IF (p^.mode # Var) OR (form # Comp) THEN
IF p^.mode = VarPar THEN
IF form = Comp THEN comp := typ^.comp;
IF comp = DynArr THEN nrReg := typ^.n+2
ELSIF comp = Record THEN nrReg := 2
ELSE nrReg := 1
END
ELSE nrReg := 1
END;
typ := OPT.linttyp
ELSE
nrReg := 1
END;
ralloc := -1-p^.adr; y.mode := SHORT(SHORT(ralloc DIV 32)); y.reg := ralloc MOD 32;
(*y.typ := OPT.linttyp;*) y.typ := typ;
y.Tjmp := 0; y.Fjmp := 0; ralloc := p^.linkadr; rdest := ralloc < 0;
IF rdest THEN ralloc := -1-ralloc; x.mode := SHORT(SHORT(ralloc DIV 32)); x.reg := ralloc MOD 32
ELSE x.mode := Based; x.reg := FP; x.offset := ralloc
END;
(*x.typ := OPT.linttyp;*) x.typ := typ;
REPEAT
Assign(x, y); INC(y.reg); DEC(nrReg);
IF rdest THEN INC(x.reg, 1) ELSE INC(x.offset, 4) END
UNTIL nrReg = 0
END
END;
p := p^.link
END
END;
aopSize := 0; sSize := 0; SLsize := 0; SBoffset := fsize+20;
IF (n # NIL) & (n^.mnolev > 0) THEN
y.mode := Reg; y.reg := SLpar; y.typ := OPT.linttyp;
x.mode := Based; x.reg := FP; x.offset := -4; x.typ := OPT.linttyp;
Assign(x, y); SLsize := 8
END;
IF n # NIL THEN p := n^.link; FPlink := 0; FPlink4 := 0;
WHILE p # NIL DO
typ := p^.typ; form := typ^.form;
IF (p^.mode = Var) & (form = Comp) THEN
comp := typ^.comp;
IF comp = DynArr THEN DynArrCopy(p, leaf, calloc < 19)
ELSE
ralloc := p^.adr; y.typ := OPT.linttyp;
IF ralloc < 0 THEN y.reg := (-1-ralloc) MOD 32
ELSE y.mode := Based; y.reg := FP; y.offset := ralloc+fsize; Load(y, -1)
END;
y.mode := Based; y.typ := p^.typ; y.offset := 0;
x.mode := Based; x.reg := FP; x.offset := p^.linkadr; x.typ := p^.typ;
Assign(x, y)
END
END;
p := p^.link
END
END;
IF (n # NIL) & (ptrinit IN options) THEN InitPtrs(n) END;
leaveProc := 0;
END Enter;
PROCEDURE Leave* (VAR n: OPT.Object);
VAR regs, fsize, psize: LONGINT;
BEGIN
INC(sSize, sSize MOD 8); psize := aopSize+sSize+SLsize+8*4+6*4; INC(psize, psize MOD 8);
IF n # NIL THEN
OPL.FixupFP(FPlink, FPlink4, psize-(sSize+SLsize));
IF n^.typ^.form # NoTyp THEN
IF n^.typ^.form IN {Real, LReal} THEN OPL.LockParF(1)
ELSE
IF n^.typ^.form = ProcTyp THEN OPL.LockParR(4) END;
OPL.LockParR(3)
END;
OPL.SetTrap(FuncTrap); OPL.Put(iT+cALWAYS*fTO)
END;
SetLabel(leaveProc);
regs := n^.conval^.intval; fsize := n^.conval^.intval2;
OPL.GenProcExit(fsize, psize, (regs DIV 1024) MOD 32, (regs DIV 32) MOD 32, regs MOD 32, FP, n^.leaf);
OPL.FreePar;
OPL.OutRefPoint(fsize, psize, (regs DIV 1024) MOD 32, (regs DIV 32) MOD 32, regs MOD 32, n^.leaf)
ELSE
SetLabel(leaveProc);
OPL.GenProcExit(8, psize, 30, 31, 19, FP, FALSE);
OPL.OutRefPoint(8, psize, 30, 31, 19, FALSE)
END
END Leave;
PROCEDURE Return* (VAR x: OPL.Item);
BEGIN
IF x.mode = FReg THEN OPL.FreeTempF(x.reg)
ELSIF x.mode = Reg THEN OPL.FreeTempR(x.reg);
IF x.typ^.form = ProcTyp THEN OPL.FreeTempR(x.reg+1) END
END;
PutBranch(leaveProc)
END Return;
PROCEDURE Assign* (VAR x, y: OPL.Item);
VAR rt, t: LONGINT; z: OPL.Item;
BEGIN
IF y.typ^.form = Comp THEN
z.mode := Con; z.typ := OPT.linttyp; z.offset := x.typ^.size; Move(x, y, z, FALSE)
ELSIF x.typ^.form = ProcTyp THEN
IF y.mode = XProc THEN
rt := -1; IF x.mode = Reg THEN rt := x.reg END;
z := y; OPL.LoadProcAddr(z, rt); x.typ := OPT.linttyp; Assign(x, z);
IF y.mnolev = 0 THEN y.mode := Reg ELSE y.mode := Based; y.offset := -(y.mnolev*4)+OPL.linkTable END;
y.reg := SB; y.typ := OPT.linttyp;
IF x.mode = Reg THEN INC(x.reg) ELSE INC(x.offset, 4) END;
Assign(x, y)
ELSIF y.mode = Con THEN ASSERT(y.typ^.form = NilTyp);
IF x.mode # Reg THEN Base(x, -1) END;
x.typ := OPT.linttyp; z := zero; Assign(x, z);
IF x.mode = Reg THEN INC(x.reg) ELSE INC(x.offset, 4) END;
Assign(x, z)
ELSE
IF x.mode # Reg THEN Base(x, -1) END;
IF y.mode # Reg THEN Base(y, -1) END;
x.typ := OPT.linttyp; y.typ := OPT.linttyp;
z := y; Assign(x, y);
IF x.mode = Reg THEN INC(x.reg) ELSE INC(x.offset, 4) END;
IF z.mode = Reg THEN INC(z.reg) ELSE INC(z.offset, 4) END;
Assign(x, z)
END
ELSIF y.typ^.form = String THEN
Copy(x, y)
ELSIF (y.typ^.form = Bool) & (y.mode = Con) & (x.mode = Cond) THEN
rt := x.reg; ASSERT((0 <= rt) & (rt <= 31));
IF y.offset = 0 THEN OPL.Put(iCRXOR+rt*fBT) ELSE OPL.Put(iCREQV+rt*fBT) END
ELSE t := -1; rt := -1;
IF x.mode = Reg THEN
rt := x.reg; IF (y.typ^.form # SInt) OR (y.mode = Con) THEN t := rt END
ELSIF x.mode = FReg THEN
rt := x.reg; IF y.typ^.form IN {Real, LReal} THEN t := x.reg END
END;
Load(y, t); Convert(y, x.typ, rt, x.mode = FReg); Store(x, y)
END
END Assign;
PROCEDURE Increment* (VAR x, y: OPL.Item; inc: BOOLEAN);
VAR z: OPL.Item;
BEGIN
IF x.mode = Reg THEN
IF inc THEN Plus(x, y, x.reg) ELSE Minus(x, y, x.reg) END
ELSE BaseOrInx(x, -1);
IF x.mode = Based THEN ShortBase(x, -1) END;
z := x; IF inc THEN Plus(x, y, -1) ELSE Minus(x, y, -1) END;
Store(z, x)
END
END Increment;
PROCEDURE Include* (VAR x, y: OPL.Item);
VAR z: OPL.Item;
BEGIN
IF y.mode = Con THEN
IF OPM.CeresVersion THEN y.offset := SYSTEM.VAL(LONGINT, {31-y.offset})
ELSE y.offset := SYSTEM.VAL(LONGINT, {y.offset})
END;
y.typ := OPT.settyp
ELSE SetElem(y, -1)
END;
IF x.mode = Reg THEN Plus(x, y, x.reg)
ELSE BaseOrInx(x, -1);
IF x.mode = Based THEN ShortBase(x, -1) END;
z := x; Plus(x, y, -1); Store(z, x)
END
END Include;
PROCEDURE Exclude* (VAR x, y: OPL.Item);
VAR ycon: BOOLEAN; bit, s, t: LONGINT; z: OPL.Item;
BEGIN
ycon := y.mode = Con;
IF ycon THEN bit := y.offset ELSE SetElem(y, -1) END;
IF x.mode = Reg THEN
IF ycon THEN OPL.Put(iRLINM+x.reg*fRA+x.reg*fRS+((bit+1) MOD 32)*fMB+((bit-1) MOD 32)*fME)
ELSE Minus(x, y, x.reg)
END
ELSE BaseOrInx(x, -1);
IF x.mode = Based THEN ShortBase(x, -1) END;
z := x;
IF ycon THEN Load(x, -1); s := x.reg; OPL.FreeTempR(s); t := OPL.GetTempR(); OPL.FreeTempR(t);
OPL.Put(iRLINM+t*fRA+s*fRS+((bit+1) MOD 32)*fMB+((bit-1) MOD 32)*fME); x.reg := t
ELSE Minus(x, y, -1)
END;
Store(z, x)
END
END Exclude;
PROCEDURE Init* (opt: SET);
BEGIN
options := opt; IntToRealAddr := 0; LoopLevel := OPM.MaxExit;
CaseLink := -1; NewRecEntry := -1; NewSysEntry := -1; NewArrEntry := -1;
scratch := -1; RealToIntAddr := 0
END Init;
BEGIN
BLI[Undef] := -1; BLI[Byte] := iLBZ; BLI[Bool] := iLBZ; BLI[Char] := iLBZ; BLI[SInt] := iLBZ; BLI[Int] := iLHA;
BLI[LInt] := iL; BLI[Real] := iLFS; BLI[LReal] := iLFD; BLI[Set] := iL; BLI[String] := -1; BLI[NilTyp] := iL;
BLI[NoTyp] := -1; BLI[Pointer] := iL; XLI[Undef] := -1; XLI[Byte] := iLBZX; XLI[Bool] := iLBZX; XLI[Char] := iLBZX;
XLI[SInt] := iLBZX; XLI[Int] := iLHAX; XLI[LInt] := iLX; XLI[Real] := iLFSX; XLI[LReal] := iLFDX; XLI[Set] := iLX;
XLI[String] := -1; XLI[NilTyp] := iLX; XLI[NoTyp] := -1; XLI[Pointer] := iLX;
BSI[Undef] := -1; BSI[Byte] := iSTB; BSI[Bool] := iSTB; BSI[Char] := iSTB; BSI[SInt] := iSTB; BSI[Int] := iSTH;
BSI[LInt] := iST; BSI[Real] := iSTFS; BSI[LReal] := iSTFD; BSI[Set] := iST; BSI[String] := -1; BSI[NilTyp] := iST;
BSI[NoTyp] := -1; BSI[Pointer] := iST; XSI[Undef] := -1; XSI[Byte] := iSTBX; XSI[Bool] := iSTBX; XSI[Char] := iSTBX;
XSI[SInt] := iSTBX; XSI[Int] := iSTHX; XSI[LInt] := iSTX; XSI[Real] := iSTFSX; XSI[LReal] := iSTFDX; XSI[Set] := iSTX;
XSI[String] := -1; XSI[NilTyp] := iSTX; XSI[NoTyp] := -1; XSI[Pointer] := iSTX;
IntToRealBlock[0] := 43X; IntToRealBlock[1] := 30X; IntToRealBlock[2] := 0X; IntToRealBlock[3] := 0X;
IntToRealBlock[4] := 80X; IntToRealBlock[5] := 0X; IntToRealBlock[6] := 0X; IntToRealBlock[7] := 0X;
IntToRealBlock[8] := 43X; IntToRealBlock[9] := 30X; IntToRealBlock[10] := 0X; IntToRealBlock[11] := 0X;
IntToRealBlock[12] := 0X; IntToRealBlock[13] := 0X; IntToRealBlock[14] := 0X; IntToRealBlock[15] := 0X;
RealToIntBlock[0] := 43X; RealToIntBlock[1] := 30X; RealToIntBlock[2] := 0X; RealToIntBlock[3] := 1X;
RealToIntBlock[4] := 0X; RealToIntBlock[5] := 0X; RealToIntBlock[6] := 0X; RealToIntBlock[7] := 0X;
zero.mode := Con; zero.offset := 0; zero.typ := OPT.linttyp; zero.dreg := -1;
CAPmask.mode := Con; CAPmask.offset := 5FH; CAPmask.typ := OPT.settyp; CAPmask.dreg := -1;
CRbit[eql-eql] := bEQ; CRbit[neq-eql] := -1-bEQ; CRbit[lss-eql] := bLT; CRbit[leq-eql] := -1-bGT;
CRbit[gtr-eql] := bGT; CRbit[geq-eql] := -1-bLT;
switch[eql-eql] := eql; switch[neq-eql] := neq; switch[lss-eql] := gtr; switch[leq-eql] := geq;
switch[gtr-eql] := lss; switch[geq-eql] := leq
END POPC.